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
351892a8
Commit
351892a8
authored
Nov 27, 2013
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/hda' into for-next
parents
d2208ca0
0e24dbb7
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
166 additions
and
70 deletions
+166
-70
sound/pci/hda/Makefile
sound/pci/hda/Makefile
+4
-1
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.c
+140
-45
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_codec.h
+7
-1
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.c
+4
-0
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+1
-1
sound/pci/hda/hda_local.h
sound/pci/hda/hda_local.h
+1
-7
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_hdmi.c
+9
-15
No files found.
sound/pci/hda/Makefile
View file @
351892a8
...
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
...
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
snd-hda-intel-$(CONFIG_SND_HDA_I915)
+=
hda_i915.o
snd-hda-intel-$(CONFIG_SND_HDA_I915)
+=
hda_i915.o
snd-hda-codec-y
:=
hda_codec.o hda_jack.o hda_auto_parser.o
snd-hda-codec-y
:=
hda_codec.o hda_jack.o hda_auto_parser.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC)
+=
hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS)
+=
hda_proc.o
snd-hda-codec-$(CONFIG_PROC_FS)
+=
hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP)
+=
hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP)
+=
hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP)
+=
hda_beep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP)
+=
hda_beep.o
...
@@ -12,6 +11,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
...
@@ -12,6 +11,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
CFLAGS_hda_codec.o
:=
-I
$(src)
CFLAGS_hda_codec.o
:=
-I
$(src)
CFLAGS_hda_intel.o
:=
-I
$(src)
CFLAGS_hda_intel.o
:=
-I
$(src)
snd-hda-codec-generic-objs
:=
hda_generic.o
snd-hda-codec-realtek-objs
:=
patch_realtek.o
snd-hda-codec-realtek-objs
:=
patch_realtek.o
snd-hda-codec-cmedia-objs
:=
patch_cmedia.o
snd-hda-codec-cmedia-objs
:=
patch_cmedia.o
snd-hda-codec-analog-objs
:=
patch_analog.o
snd-hda-codec-analog-objs
:=
patch_analog.o
...
@@ -28,6 +28,9 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
...
@@ -28,6 +28,9 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
obj-$(CONFIG_SND_HDA_INTEL)
:=
snd-hda-codec.o
obj-$(CONFIG_SND_HDA_INTEL)
:=
snd-hda-codec.o
# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
ifdef
CONFIG_SND_HDA_GENERIC
obj-$(CONFIG_SND_HDA_INTEL)
+=
snd-hda-codec-generic.o
endif
ifdef
CONFIG_SND_HDA_CODEC_REALTEK
ifdef
CONFIG_SND_HDA_CODEC_REALTEK
obj-$(CONFIG_SND_HDA_INTEL)
+=
snd-hda-codec-realtek.o
obj-$(CONFIG_SND_HDA_INTEL)
+=
snd-hda-codec-realtek.o
endif
endif
...
...
sound/pci/hda/hda_codec.c
View file @
351892a8
...
@@ -96,19 +96,28 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
...
@@ -96,19 +96,28 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
#ifdef CONFIG_PM
#ifdef CONFIG_PM
#define codec_in_pm(codec) ((codec)->in_pm)
#define codec_in_pm(codec) ((codec)->in_pm)
static
void
hda_pm_work
(
struct
work_struct
*
work
);
static
void
hda_power_work
(
struct
work_struct
*
work
);
static
void
hda_power_work
(
struct
work_struct
*
work
);
static
void
hda_keep_power_on
(
struct
hda_codec
*
codec
);
static
void
hda_keep_power_on
(
struct
hda_codec
*
codec
);
#define hda_codec_is_power_on(codec) ((codec)->power_on)
#define hda_codec_is_power_on(codec) ((codec)->power_on)
static
inline
void
hda_call_pm_notify
(
struct
hda_bus
*
bus
,
bool
power_up
)
static
void
hda_call_pm_notify
(
struct
hda_codec
*
codec
,
bool
power_up
)
{
{
struct
hda_bus
*
bus
=
codec
->
bus
;
if
((
power_up
&&
codec
->
pm_up_notified
)
||
(
!
power_up
&&
!
codec
->
pm_up_notified
))
return
;
if
(
bus
->
ops
.
pm_notify
)
if
(
bus
->
ops
.
pm_notify
)
bus
->
ops
.
pm_notify
(
bus
,
power_up
);
bus
->
ops
.
pm_notify
(
bus
,
power_up
);
codec
->
pm_up_notified
=
power_up
;
}
}
#else
#else
#define codec_in_pm(codec) 0
#define codec_in_pm(codec) 0
static
inline
void
hda_keep_power_on
(
struct
hda_codec
*
codec
)
{}
static
inline
void
hda_keep_power_on
(
struct
hda_codec
*
codec
)
{}
#define hda_codec_is_power_on(codec) 1
#define hda_codec_is_power_on(codec) 1
#define hda_call_pm_notify(
bus
, state) {}
#define hda_call_pm_notify(
codec
, state) {}
#endif
#endif
/**
/**
...
@@ -831,6 +840,12 @@ static int snd_hda_bus_free(struct hda_bus *bus)
...
@@ -831,6 +840,12 @@ static int snd_hda_bus_free(struct hda_bus *bus)
bus
->
ops
.
private_free
(
bus
);
bus
->
ops
.
private_free
(
bus
);
if
(
bus
->
workq
)
if
(
bus
->
workq
)
destroy_workqueue
(
bus
->
workq
);
destroy_workqueue
(
bus
->
workq
);
#ifdef CONFIG_PM
if
(
bus
->
pm_wq
)
destroy_workqueue
(
bus
->
pm_wq
);
#endif
kfree
(
bus
);
kfree
(
bus
);
return
0
;
return
0
;
}
}
...
@@ -875,6 +890,9 @@ int snd_hda_bus_new(struct snd_card *card,
...
@@ -875,6 +890,9 @@ int snd_hda_bus_new(struct snd_card *card,
.
dev_register
=
snd_hda_bus_dev_register
,
.
dev_register
=
snd_hda_bus_dev_register
,
.
dev_free
=
snd_hda_bus_dev_free
,
.
dev_free
=
snd_hda_bus_dev_free
,
};
};
#ifdef CONFIG_PM
char
wqname
[
16
];
#endif
if
(
snd_BUG_ON
(
!
temp
))
if
(
snd_BUG_ON
(
!
temp
))
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -911,6 +929,16 @@ int snd_hda_bus_new(struct snd_card *card,
...
@@ -911,6 +929,16 @@ int snd_hda_bus_new(struct snd_card *card,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
#ifdef CONFIG_PM
sprintf
(
wqname
,
"hda-pm-wq-%d"
,
card
->
number
);
bus
->
pm_wq
=
create_workqueue
(
wqname
);
if
(
!
bus
->
pm_wq
)
{
snd_printk
(
KERN_ERR
"cannot create PM workqueue
\n
"
);
snd_hda_bus_free
(
bus
);
return
-
ENOMEM
;
}
#endif
err
=
snd_device_new
(
card
,
SNDRV_DEV_BUS
,
bus
,
&
dev_ops
);
err
=
snd_device_new
(
card
,
SNDRV_DEV_BUS
,
bus
,
&
dev_ops
);
if
(
err
<
0
)
{
if
(
err
<
0
)
{
snd_hda_bus_free
(
bus
);
snd_hda_bus_free
(
bus
);
...
@@ -945,9 +973,6 @@ find_codec_preset(struct hda_codec *codec)
...
@@ -945,9 +973,6 @@ find_codec_preset(struct hda_codec *codec)
const
struct
hda_codec_preset
*
preset
;
const
struct
hda_codec_preset
*
preset
;
unsigned
int
mod_requested
=
0
;
unsigned
int
mod_requested
=
0
;
if
(
is_generic_config
(
codec
))
return
NULL
;
/* use the generic parser */
again:
again:
mutex_lock
(
&
preset_mutex
);
mutex_lock
(
&
preset_mutex
);
list_for_each_entry
(
tbl
,
&
hda_preset_tables
,
list
)
{
list_for_each_entry
(
tbl
,
&
hda_preset_tables
,
list
)
{
...
@@ -1329,6 +1354,28 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
...
@@ -1329,6 +1354,28 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
return
p
;
return
p
;
}
}
/*
* Dynamic symbol binding for the codec parsers
*/
#ifdef MODULE
#define load_parser_sym(sym) ((int (*)(struct hda_codec *))symbol_request(sym))
#define unload_parser_addr(addr) symbol_put_addr(addr)
#else
#define load_parser_sym(sym) (sym)
#define unload_parser_addr(addr) do {} while (0)
#endif
#define load_parser(codec, sym) \
((codec)->parser = load_parser_sym(sym))
static
void
unload_parser
(
struct
hda_codec
*
codec
)
{
if
(
codec
->
parser
)
{
unload_parser_addr
(
codec
->
parser
);
codec
->
parser
=
NULL
;
}
}
/*
/*
* codec destructor
* codec destructor
*/
*/
...
@@ -1352,10 +1399,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
...
@@ -1352,10 +1399,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
codec
->
bus
->
caddr_tbl
[
codec
->
addr
]
=
NULL
;
codec
->
bus
->
caddr_tbl
[
codec
->
addr
]
=
NULL
;
if
(
codec
->
patch_ops
.
free
)
if
(
codec
->
patch_ops
.
free
)
codec
->
patch_ops
.
free
(
codec
);
codec
->
patch_ops
.
free
(
codec
);
#ifdef CONFIG_PM
hda_call_pm_notify
(
codec
,
false
);
/* cancel leftover refcounts */
if
(
!
codec
->
pm_down_notified
)
/* cancel leftover refcounts */
unload_parser
(
codec
);
hda_call_pm_notify
(
codec
->
bus
,
false
);
#endif
module_put
(
codec
->
owner
);
module_put
(
codec
->
owner
);
free_hda_cache
(
&
codec
->
amp_cache
);
free_hda_cache
(
&
codec
->
amp_cache
);
free_hda_cache
(
&
codec
->
cmd_cache
);
free_hda_cache
(
&
codec
->
cmd_cache
);
...
@@ -1363,6 +1408,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
...
@@ -1363,6 +1408,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
kfree
(
codec
->
chip_name
);
kfree
(
codec
->
chip_name
);
kfree
(
codec
->
modelname
);
kfree
(
codec
->
modelname
);
kfree
(
codec
->
wcaps
);
kfree
(
codec
->
wcaps
);
codec
->
bus
->
num_codecs
--
;
kfree
(
codec
);
kfree
(
codec
);
}
}
...
@@ -1428,12 +1474,12 @@ int snd_hda_codec_new(struct hda_bus *bus,
...
@@ -1428,12 +1474,12 @@ int snd_hda_codec_new(struct hda_bus *bus,
#ifdef CONFIG_PM
#ifdef CONFIG_PM
spin_lock_init
(
&
codec
->
power_lock
);
spin_lock_init
(
&
codec
->
power_lock
);
INIT_DELAYED_WORK
(
&
codec
->
power_work
,
hda_power_work
);
INIT_DELAYED_WORK
(
&
codec
->
power_work
,
hda_power_work
);
INIT_WORK
(
&
codec
->
pm_work
,
hda_pm_work
);
/* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
/* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
* the caller has to power down appropriatley after initialization
* the caller has to power down appropriatley after initialization
* phase.
* phase.
*/
*/
hda_keep_power_on
(
codec
);
hda_keep_power_on
(
codec
);
hda_call_pm_notify
(
bus
,
true
);
#endif
#endif
if
(
codec
->
bus
->
modelname
)
{
if
(
codec
->
bus
->
modelname
)
{
...
@@ -1445,6 +1491,11 @@ int snd_hda_codec_new(struct hda_bus *bus,
...
@@ -1445,6 +1491,11 @@ int snd_hda_codec_new(struct hda_bus *bus,
}
}
list_add_tail
(
&
codec
->
list
,
&
bus
->
codec_list
);
list_add_tail
(
&
codec
->
list
,
&
bus
->
codec_list
);
bus
->
num_codecs
++
;
#ifdef CONFIG_PM
workqueue_set_max_active
(
bus
->
pm_wq
,
bus
->
num_codecs
);
#endif
bus
->
caddr_tbl
[
codec_addr
]
=
codec
;
bus
->
caddr_tbl
[
codec_addr
]
=
codec
;
codec
->
vendor_id
=
snd_hda_param_read
(
codec
,
AC_NODE_ROOT
,
codec
->
vendor_id
=
snd_hda_param_read
(
codec
,
AC_NODE_ROOT
,
...
@@ -1486,11 +1537,14 @@ int snd_hda_codec_new(struct hda_bus *bus,
...
@@ -1486,11 +1537,14 @@ int snd_hda_codec_new(struct hda_bus *bus,
#ifdef CONFIG_PM
#ifdef CONFIG_PM
codec
->
d3_stop_clk
=
snd_hda_codec_get_supported_ps
(
codec
,
fg
,
codec
->
d3_stop_clk
=
snd_hda_codec_get_supported_ps
(
codec
,
fg
,
AC_PWRST_CLKSTOP
);
AC_PWRST_CLKSTOP
);
if
(
!
codec
->
d3_stop_clk
)
bus
->
power_keep_link_on
=
1
;
#endif
#endif
codec
->
epss
=
snd_hda_codec_get_supported_ps
(
codec
,
fg
,
codec
->
epss
=
snd_hda_codec_get_supported_ps
(
codec
,
fg
,
AC_PWRST_EPSS
);
AC_PWRST_EPSS
);
#ifdef CONFIG_PM
if
(
!
codec
->
d3_stop_clk
||
!
codec
->
epss
)
bus
->
power_keep_link_on
=
1
;
#endif
/* power-up all before initialization */
/* power-up all before initialization */
hda_set_power_state
(
codec
,
AC_PWRST_D0
);
hda_set_power_state
(
codec
,
AC_PWRST_D0
);
...
@@ -1537,6 +1591,31 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
...
@@ -1537,6 +1591,31 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
EXPORT_SYMBOL_HDA
(
snd_hda_codec_update_widgets
);
EXPORT_SYMBOL_HDA
(
snd_hda_codec_update_widgets
);
#ifdef CONFIG_SND_HDA_CODEC_HDMI
/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
static
bool
is_likely_hdmi_codec
(
struct
hda_codec
*
codec
)
{
hda_nid_t
nid
=
codec
->
start_nid
;
int
i
;
for
(
i
=
0
;
i
<
codec
->
num_nodes
;
i
++
,
nid
++
)
{
unsigned
int
wcaps
=
get_wcaps
(
codec
,
nid
);
switch
(
get_wcaps_type
(
wcaps
))
{
case
AC_WID_AUD_IN
:
return
false
;
/* HDMI parser supports only HDMI out */
case
AC_WID_AUD_OUT
:
if
(
!
(
wcaps
&
AC_WCAP_DIGITAL
))
return
false
;
break
;
}
}
return
true
;
}
#else
/* no HDMI codec parser support */
#define is_likely_hdmi_codec(codec) false
#endif
/* CONFIG_SND_HDA_CODEC_HDMI */
/**
/**
* snd_hda_codec_configure - (Re-)configure the HD-audio codec
* snd_hda_codec_configure - (Re-)configure the HD-audio codec
* @codec: the HDA codec
* @codec: the HDA codec
...
@@ -1548,6 +1627,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
...
@@ -1548,6 +1627,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
*/
*/
int
snd_hda_codec_configure
(
struct
hda_codec
*
codec
)
int
snd_hda_codec_configure
(
struct
hda_codec
*
codec
)
{
{
int
(
*
patch
)(
struct
hda_codec
*
)
=
NULL
;
int
err
;
int
err
;
codec
->
preset
=
find_codec_preset
(
codec
);
codec
->
preset
=
find_codec_preset
(
codec
);
...
@@ -1557,29 +1637,40 @@ int snd_hda_codec_configure(struct hda_codec *codec)
...
@@ -1557,29 +1637,40 @@ int snd_hda_codec_configure(struct hda_codec *codec)
return
err
;
return
err
;
}
}
if
(
is_generic_config
(
codec
))
{
if
(
!
is_generic_config
(
codec
)
&&
codec
->
preset
)
err
=
snd_hda_parse_generic_codec
(
codec
);
patch
=
codec
->
preset
->
patch
;
goto
patched
;
if
(
!
patch
)
{
}
unload_parser
(
codec
);
/* to be sure */
if
(
codec
->
preset
&&
codec
->
preset
->
patch
)
{
if
(
is_likely_hdmi_codec
(
codec
))
err
=
codec
->
preset
->
patch
(
codec
);
patch
=
load_parser
(
codec
,
snd_hda_parse_hdmi_codec
);
goto
patched
;
#ifdef CONFIG_SND_HDA_GENERIC
if
(
!
patch
)
patch
=
load_parser
(
codec
,
snd_hda_parse_generic_codec
);
#endif
if
(
!
patch
)
{
printk
(
KERN_ERR
"hda-codec: No codec parser is available
\n
"
);
return
-
ENODEV
;
}
}
}
/* call the default parser */
err
=
patch
(
codec
);
err
=
snd_hda_parse_generic_codec
(
codec
);
if
(
err
<
0
)
{
if
(
err
<
0
)
unload_parser
(
codec
);
printk
(
KERN_ERR
"hda-codec: No codec parser is available
\n
"
);
return
err
;
}
patched:
if
(
codec
->
patch_ops
.
unsol_event
)
{
if
(
!
err
&&
codec
->
patch_ops
.
unsol_event
)
err
=
init_unsol_queue
(
codec
->
bus
);
err
=
init_unsol_queue
(
codec
->
bus
);
if
(
err
<
0
)
return
err
;
}
/* audio codec should override the mixer name */
/* audio codec should override the mixer name */
if
(
!
err
&&
(
codec
->
afg
||
!*
codec
->
bus
->
card
->
mixername
)
)
if
(
codec
->
afg
||
!*
codec
->
bus
->
card
->
mixername
)
snprintf
(
codec
->
bus
->
card
->
mixername
,
snprintf
(
codec
->
bus
->
card
->
mixername
,
sizeof
(
codec
->
bus
->
card
->
mixername
),
sizeof
(
codec
->
bus
->
card
->
mixername
),
"%s %s"
,
codec
->
vendor_name
,
codec
->
chip_name
);
"%s %s"
,
codec
->
vendor_name
,
codec
->
chip_name
);
return
err
;
return
0
;
}
}
EXPORT_SYMBOL_HDA
(
snd_hda_codec_configure
);
EXPORT_SYMBOL_HDA
(
snd_hda_codec_configure
);
...
@@ -2610,6 +2701,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
...
@@ -2610,6 +2701,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
codec
->
preset
=
NULL
;
codec
->
preset
=
NULL
;
codec
->
slave_dig_outs
=
NULL
;
codec
->
slave_dig_outs
=
NULL
;
codec
->
spdif_status_reset
=
0
;
codec
->
spdif_status_reset
=
0
;
unload_parser
(
codec
);
module_put
(
codec
->
owner
);
module_put
(
codec
->
owner
);
codec
->
owner
=
NULL
;
codec
->
owner
=
NULL
;
...
@@ -4000,10 +4092,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
...
@@ -4000,10 +4092,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
* in the resume / power-save sequence
* in the resume / power-save sequence
*/
*/
hda_keep_power_on
(
codec
);
hda_keep_power_on
(
codec
);
if
(
codec
->
pm_down_notified
)
{
codec
->
pm_down_notified
=
0
;
hda_call_pm_notify
(
codec
->
bus
,
true
);
}
hda_set_power_state
(
codec
,
AC_PWRST_D0
);
hda_set_power_state
(
codec
,
AC_PWRST_D0
);
restore_shutup_pins
(
codec
);
restore_shutup_pins
(
codec
);
hda_exec_init_verbs
(
codec
);
hda_exec_init_verbs
(
codec
);
...
@@ -4877,11 +4965,8 @@ static void hda_power_work(struct work_struct *work)
...
@@ -4877,11 +4965,8 @@ static void hda_power_work(struct work_struct *work)
spin_unlock
(
&
codec
->
power_lock
);
spin_unlock
(
&
codec
->
power_lock
);
state
=
hda_call_codec_suspend
(
codec
,
true
);
state
=
hda_call_codec_suspend
(
codec
,
true
);
if
(
!
codec
->
pm_down_notified
&&
if
(
!
bus
->
power_keep_link_on
&&
(
state
&
AC_PWRST_CLK_STOP_OK
))
!
bus
->
power_keep_link_on
&&
(
state
&
AC_PWRST_CLK_STOP_OK
))
{
hda_call_pm_notify
(
codec
,
false
);
codec
->
pm_down_notified
=
1
;
hda_call_pm_notify
(
bus
,
false
);
}
}
}
static
void
hda_keep_power_on
(
struct
hda_codec
*
codec
)
static
void
hda_keep_power_on
(
struct
hda_codec
*
codec
)
...
@@ -4891,6 +4976,7 @@ static void hda_keep_power_on(struct hda_codec *codec)
...
@@ -4891,6 +4976,7 @@ static void hda_keep_power_on(struct hda_codec *codec)
codec
->
power_on
=
1
;
codec
->
power_on
=
1
;
codec
->
power_jiffies
=
jiffies
;
codec
->
power_jiffies
=
jiffies
;
spin_unlock
(
&
codec
->
power_lock
);
spin_unlock
(
&
codec
->
power_lock
);
hda_call_pm_notify
(
codec
,
true
);
}
}
/* update the power on/off account with the current jiffies */
/* update the power on/off account with the current jiffies */
...
@@ -4910,8 +4996,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
...
@@ -4910,8 +4996,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
/* call this with codec->power_lock held! */
/* call this with codec->power_lock held! */
static
void
__snd_hda_power_up
(
struct
hda_codec
*
codec
,
bool
wait_power_down
)
static
void
__snd_hda_power_up
(
struct
hda_codec
*
codec
,
bool
wait_power_down
)
{
{
struct
hda_bus
*
bus
=
codec
->
bus
;
/* Return if power_on or transitioning to power_on, unless currently
/* Return if power_on or transitioning to power_on, unless currently
* powering down. */
* powering down. */
if
((
codec
->
power_on
||
codec
->
power_transition
>
0
)
&&
if
((
codec
->
power_on
||
codec
->
power_transition
>
0
)
&&
...
@@ -4938,11 +5022,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
...
@@ -4938,11 +5022,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
codec
->
power_transition
=
1
;
/* avoid reentrance */
codec
->
power_transition
=
1
;
/* avoid reentrance */
spin_unlock
(
&
codec
->
power_lock
);
spin_unlock
(
&
codec
->
power_lock
);
if
(
codec
->
pm_down_notified
)
{
codec
->
pm_down_notified
=
0
;
hda_call_pm_notify
(
bus
,
true
);
}
hda_call_codec_resume
(
codec
);
hda_call_codec_resume
(
codec
);
spin_lock
(
&
codec
->
power_lock
);
spin_lock
(
&
codec
->
power_lock
);
...
@@ -5036,6 +5115,14 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
...
@@ -5036,6 +5115,14 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
return
0
;
return
0
;
}
}
EXPORT_SYMBOL_HDA
(
snd_hda_check_amp_list_power
);
EXPORT_SYMBOL_HDA
(
snd_hda_check_amp_list_power
);
static
void
hda_pm_work
(
struct
work_struct
*
work
)
{
struct
hda_codec
*
codec
=
container_of
(
work
,
struct
hda_codec
,
pm_work
);
hda_call_codec_suspend
(
codec
,
false
);
}
#endif
#endif
/*
/*
...
@@ -5611,9 +5698,17 @@ int snd_hda_suspend(struct hda_bus *bus)
...
@@ -5611,9 +5698,17 @@ int snd_hda_suspend(struct hda_bus *bus)
list_for_each_entry
(
codec
,
&
bus
->
codec_list
,
list
)
{
list_for_each_entry
(
codec
,
&
bus
->
codec_list
,
list
)
{
cancel_delayed_work_sync
(
&
codec
->
jackpoll_work
);
cancel_delayed_work_sync
(
&
codec
->
jackpoll_work
);
if
(
hda_codec_is_power_on
(
codec
))
if
(
hda_codec_is_power_on
(
codec
))
{
hda_call_codec_suspend
(
codec
,
false
);
if
(
bus
->
num_codecs
>
1
)
queue_work
(
bus
->
pm_wq
,
&
codec
->
pm_work
);
else
hda_call_codec_suspend
(
codec
,
false
);
}
}
}
if
(
bus
->
num_codecs
>
1
)
flush_workqueue
(
bus
->
pm_wq
);
return
0
;
return
0
;
}
}
EXPORT_SYMBOL_HDA
(
snd_hda_suspend
);
EXPORT_SYMBOL_HDA
(
snd_hda_suspend
);
...
...
sound/pci/hda/hda_codec.h
View file @
351892a8
...
@@ -673,6 +673,7 @@ struct hda_bus {
...
@@ -673,6 +673,7 @@ struct hda_bus {
/* codec linked list */
/* codec linked list */
struct
list_head
codec_list
;
struct
list_head
codec_list
;
unsigned
int
num_codecs
;
/* link caddr -> codec */
/* link caddr -> codec */
struct
hda_codec
*
caddr_tbl
[
HDA_MAX_CODEC_ADDRESS
+
1
];
struct
hda_codec
*
caddr_tbl
[
HDA_MAX_CODEC_ADDRESS
+
1
];
...
@@ -683,6 +684,9 @@ struct hda_bus {
...
@@ -683,6 +684,9 @@ struct hda_bus {
struct
hda_bus_unsolicited
*
unsol
;
struct
hda_bus_unsolicited
*
unsol
;
char
workq_name
[
16
];
char
workq_name
[
16
];
struct
workqueue_struct
*
workq
;
/* common workqueue for codecs */
struct
workqueue_struct
*
workq
;
/* common workqueue for codecs */
#ifdef CONFIG_PM
struct
workqueue_struct
*
pm_wq
;
/* workqueue to parallel codec PM */
#endif
/* assigned PCMs */
/* assigned PCMs */
DECLARE_BITMAP
(
pcm_dev_bits
,
SNDRV_PCM_DEVICES
);
DECLARE_BITMAP
(
pcm_dev_bits
,
SNDRV_PCM_DEVICES
);
...
@@ -834,6 +838,7 @@ struct hda_codec {
...
@@ -834,6 +838,7 @@ struct hda_codec {
/* detected preset */
/* detected preset */
const
struct
hda_codec_preset
*
preset
;
const
struct
hda_codec_preset
*
preset
;
struct
module
*
owner
;
struct
module
*
owner
;
int
(
*
parser
)(
struct
hda_codec
*
codec
);
const
char
*
vendor_name
;
/* codec vendor name */
const
char
*
vendor_name
;
/* codec vendor name */
const
char
*
chip_name
;
/* codec chip name */
const
char
*
chip_name
;
/* codec chip name */
const
char
*
modelname
;
/* model name for preset */
const
char
*
modelname
;
/* model name for preset */
...
@@ -907,7 +912,7 @@ struct hda_codec {
...
@@ -907,7 +912,7 @@ struct hda_codec {
#ifdef CONFIG_PM
#ifdef CONFIG_PM
unsigned
int
power_on
:
1
;
/* current (global) power-state */
unsigned
int
power_on
:
1
;
/* current (global) power-state */
unsigned
int
d3_stop_clk
:
1
;
/* support D3 operation without BCLK */
unsigned
int
d3_stop_clk
:
1
;
/* support D3 operation without BCLK */
unsigned
int
pm_
down_notified
:
1
;
/* PM notified to controller */
unsigned
int
pm_
up_notified
:
1
;
/* PM notified to controller */
unsigned
int
in_pm
:
1
;
/* suspend/resume being performed */
unsigned
int
in_pm
:
1
;
/* suspend/resume being performed */
int
power_transition
;
/* power-state in transition */
int
power_transition
;
/* power-state in transition */
int
power_count
;
/* current (global) power refcount */
int
power_count
;
/* current (global) power refcount */
...
@@ -916,6 +921,7 @@ struct hda_codec {
...
@@ -916,6 +921,7 @@ struct hda_codec {
unsigned
long
power_off_acct
;
unsigned
long
power_off_acct
;
unsigned
long
power_jiffies
;
unsigned
long
power_jiffies
;
spinlock_t
power_lock
;
spinlock_t
power_lock
;
struct
work_struct
pm_work
;
/* task to parallel multi-codec PM */
#endif
#endif
/* filter the requested power state per nid */
/* filter the requested power state per nid */
...
...
sound/pci/hda/hda_generic.c
View file @
351892a8
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include <linux/ctype.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_codec.h"
...
@@ -5291,3 +5292,6 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
...
@@ -5291,3 +5292,6 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
return
err
;
return
err
;
}
}
EXPORT_SYMBOL_HDA
(
snd_hda_parse_generic_codec
);
EXPORT_SYMBOL_HDA
(
snd_hda_parse_generic_codec
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"Generic HD-audio codec parser"
);
sound/pci/hda/hda_intel.c
View file @
351892a8
...
@@ -3978,7 +3978,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
...
@@ -3978,7 +3978,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.
driver_data
=
AZX_DRIVER_PCH
|
AZX_DCAPS_INTEL_PCH_NOPM
},
.
driver_data
=
AZX_DRIVER_PCH
|
AZX_DCAPS_INTEL_PCH_NOPM
},
/* Panther Point */
/* Panther Point */
{
PCI_DEVICE
(
0x8086
,
0x1e20
),
{
PCI_DEVICE
(
0x8086
,
0x1e20
),
.
driver_data
=
AZX_DRIVER_PCH
|
AZX_DCAPS_INTEL_PCH
_NOPM
},
.
driver_data
=
AZX_DRIVER_PCH
|
AZX_DCAPS_INTEL_PCH
},
/* Lynx Point */
/* Lynx Point */
{
PCI_DEVICE
(
0x8086
,
0x8c20
),
{
PCI_DEVICE
(
0x8086
,
0x8c20
),
.
driver_data
=
AZX_DRIVER_PCH
|
AZX_DCAPS_INTEL_PCH
},
.
driver_data
=
AZX_DRIVER_PCH
|
AZX_DCAPS_INTEL_PCH
},
...
...
sound/pci/hda/hda_local.h
View file @
351892a8
...
@@ -352,14 +352,8 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
...
@@ -352,14 +352,8 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
/*
/*
* generic codec parser
* generic codec parser
*/
*/
#ifdef CONFIG_SND_HDA_GENERIC
int
snd_hda_parse_generic_codec
(
struct
hda_codec
*
codec
);
int
snd_hda_parse_generic_codec
(
struct
hda_codec
*
codec
);
#else
int
snd_hda_parse_hdmi_codec
(
struct
hda_codec
*
codec
);
static
inline
int
snd_hda_parse_generic_codec
(
struct
hda_codec
*
codec
)
{
return
-
ENODEV
;
}
#endif
/*
/*
* generic proc interface
* generic proc interface
...
...
sound/pci/hda/patch_hdmi.c
View file @
351892a8
...
@@ -1692,21 +1692,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
...
@@ -1692,21 +1692,6 @@ static int hdmi_parse_codec(struct hda_codec *codec)
}
}
}
}
#ifdef CONFIG_PM
/* We're seeing some problems with unsolicited hot plug events on
* PantherPoint after S3, if this is not enabled */
if
(
codec
->
vendor_id
==
0x80862806
)
codec
->
bus
->
power_keep_link_on
=
1
;
/*
* G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
* can be lost and presence sense verb will become inaccurate if the
* HDA link is powered off at hot plug or hw initialization time.
*/
else
if
(
!
(
snd_hda_param_read
(
codec
,
codec
->
afg
,
AC_PAR_POWER_STATE
)
&
AC_PWRST_EPSS
))
codec
->
bus
->
power_keep_link_on
=
1
;
#endif
return
0
;
return
0
;
}
}
...
@@ -3213,6 +3198,15 @@ static int patch_via_hdmi(struct hda_codec *codec)
...
@@ -3213,6 +3198,15 @@ static int patch_via_hdmi(struct hda_codec *codec)
return
patch_simple_hdmi
(
codec
,
VIAHDMI_CVT_NID
,
VIAHDMI_PIN_NID
);
return
patch_simple_hdmi
(
codec
,
VIAHDMI_CVT_NID
,
VIAHDMI_PIN_NID
);
}
}
/*
* called from hda_codec.c for generic HDMI support
*/
int
snd_hda_parse_hdmi_codec
(
struct
hda_codec
*
codec
)
{
return
patch_generic_hdmi
(
codec
);
}
EXPORT_SYMBOL_HDA
(
snd_hda_parse_hdmi_codec
);
/*
/*
* patch entries
* patch entries
*/
*/
...
...
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