2010-03-08 10:44:23 +08:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* patch_hdmi.c - routines for HDMI/DisplayPort codecs
|
|
|
|
*
|
|
|
|
* Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
|
2010-09-07 18:27:25 +08:00
|
|
|
* Copyright (c) 2006 ATI Technologies Inc.
|
|
|
|
* Copyright (c) 2008 NVIDIA Corp. All rights reserved.
|
|
|
|
* Copyright (c) 2008 Wei Ni <wni@nvidia.com>
|
2010-03-08 10:44:23 +08:00
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Wu Fengguang <wfg@linux.intel.com>
|
|
|
|
*
|
|
|
|
* Maintained by:
|
|
|
|
* Wu Fengguang <wfg@linux.intel.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/slab.h>
|
2011-07-16 01:13:37 +08:00
|
|
|
#include <linux/module.h>
|
2010-09-07 18:27:25 +08:00
|
|
|
#include <sound/core.h>
|
2011-05-19 17:46:03 +08:00
|
|
|
#include <sound/jack.h>
|
2012-09-06 10:02:37 +08:00
|
|
|
#include <sound/asoundef.h>
|
2012-07-31 17:36:00 +08:00
|
|
|
#include <sound/tlv.h>
|
2010-09-07 18:27:25 +08:00
|
|
|
#include "hda_codec.h"
|
|
|
|
#include "hda_local.h"
|
2011-10-28 04:12:46 +08:00
|
|
|
#include "hda_jack.h"
|
2010-09-07 18:27:25 +08:00
|
|
|
|
2011-01-12 01:11:04 +08:00
|
|
|
static bool static_hdmi_pcm;
|
|
|
|
module_param(static_hdmi_pcm, bool, 0644);
|
|
|
|
MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
|
|
|
|
|
2013-09-05 04:36:57 +08:00
|
|
|
#define is_haswell(codec) ((codec)->vendor_id == 0x80862807)
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_spec_per_cvt {
|
|
|
|
hda_nid_t cvt_nid;
|
|
|
|
int assigned;
|
|
|
|
unsigned int channels_min;
|
|
|
|
unsigned int channels_max;
|
|
|
|
u32 rates;
|
|
|
|
u64 formats;
|
|
|
|
unsigned int maxbps;
|
|
|
|
};
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda - Remove limit of widget connections
Currently we set the max number of connections to be 32, but there
seems codec that gives longer connection lists like AD1988, and we see
errors in proc output and else. (Though, in the case of AD1988, it's
a list of all codecs connected to a single vendor widget, so this must
be something fishy, but it's still valid from the h/w design POV.)
This patch tries to remove this restriction. For efficiency, we still
use the fixed size array in the parser, but takes a dynamic array when
the size is reported to be greater than that.
Now the fixed array size is found only in patch_hdmi.c, but it should
be fine, as the codec itself can't support so many pins.
Reported-by: Raymond Yau <superquad.vortex2@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-02-08 01:18:19 +08:00
|
|
|
/* max. connections to a widget */
|
|
|
|
#define HDA_MAX_CONNECTIONS 32
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_spec_per_pin {
|
|
|
|
hda_nid_t pin_nid;
|
|
|
|
int num_mux_nids;
|
|
|
|
hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
hda_nid_t cvt_nid;
|
2011-11-16 16:29:47 +08:00
|
|
|
|
|
|
|
struct hda_codec *codec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_eld sink_eld;
|
2013-10-18 00:21:12 +08:00
|
|
|
struct mutex lock;
|
2011-11-16 16:29:47 +08:00
|
|
|
struct delayed_work work;
|
2013-02-19 23:11:26 +08:00
|
|
|
struct snd_kcontrol *eld_ctl;
|
2011-11-19 06:59:32 +08:00
|
|
|
int repoll_count;
|
2013-09-02 18:33:02 +08:00
|
|
|
bool setup; /* the stream has been set up by prepare callback */
|
|
|
|
int channels; /* current number of channels */
|
2012-09-06 23:42:08 +08:00
|
|
|
bool non_pcm;
|
2012-07-31 17:36:00 +08:00
|
|
|
bool chmap_set; /* channel-map override by ALSA API? */
|
|
|
|
unsigned char chmap[8]; /* ALSA API channel-map */
|
2013-03-13 21:40:31 +08:00
|
|
|
char pcm_name[8]; /* filled in build_pcm callbacks */
|
2013-10-18 00:21:12 +08:00
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
struct snd_info_entry *proc_entry;
|
|
|
|
#endif
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
};
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_spec {
|
|
|
|
int num_cvts;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct snd_array cvts; /* struct hdmi_spec_per_cvt */
|
|
|
|
hda_nid_t cvt_nids[4]; /* only for haswell fix */
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int num_pins;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct snd_array pins; /* struct hdmi_spec_per_pin */
|
|
|
|
struct snd_array pcm_rec; /* struct hda_pcm */
|
2012-07-31 17:36:00 +08:00
|
|
|
unsigned int channels_max; /* max over all cvts */
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2013-02-19 23:11:25 +08:00
|
|
|
struct hdmi_eld temp_eld;
|
2010-03-08 10:44:23 +08:00
|
|
|
/*
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
* Non-generic ATI/NVIDIA specific
|
2010-03-08 10:44:23 +08:00
|
|
|
*/
|
|
|
|
struct hda_multi_out multiout;
|
2012-06-15 20:34:42 +08:00
|
|
|
struct hda_pcm_stream pcm_playback;
|
2010-03-08 10:44:23 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct hdmi_audio_infoframe {
|
|
|
|
u8 type; /* 0x84 */
|
|
|
|
u8 ver; /* 0x01 */
|
|
|
|
u8 len; /* 0x0a */
|
|
|
|
|
2010-09-21 14:25:49 +08:00
|
|
|
u8 checksum;
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
|
|
|
|
u8 SS01_SF24;
|
|
|
|
u8 CXT04;
|
|
|
|
u8 CA;
|
|
|
|
u8 LFEPBL01_LSV36_DM_INH7;
|
2010-09-21 14:25:49 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct dp_audio_infoframe {
|
|
|
|
u8 type; /* 0x84 */
|
|
|
|
u8 len; /* 0x1b */
|
|
|
|
u8 ver; /* 0x11 << 2 */
|
|
|
|
|
|
|
|
u8 CC02_CT47; /* match with HDMI infoframe from this on */
|
|
|
|
u8 SS01_SF24;
|
|
|
|
u8 CXT04;
|
|
|
|
u8 CA;
|
|
|
|
u8 LFEPBL01_LSV36_DM_INH7;
|
2010-03-08 10:44:23 +08:00
|
|
|
};
|
|
|
|
|
2011-02-11 19:17:30 +08:00
|
|
|
union audio_infoframe {
|
|
|
|
struct hdmi_audio_infoframe hdmi;
|
|
|
|
struct dp_audio_infoframe dp;
|
|
|
|
u8 bytes[0];
|
|
|
|
};
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
/*
|
|
|
|
* CEA speaker placement:
|
|
|
|
*
|
|
|
|
* FLH FCH FRH
|
|
|
|
* FLW FL FLC FC FRC FR FRW
|
|
|
|
*
|
|
|
|
* LFE
|
|
|
|
* TC
|
|
|
|
*
|
|
|
|
* RL RLC RC RRC RR
|
|
|
|
*
|
|
|
|
* The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
|
|
|
|
* CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
|
|
|
|
*/
|
|
|
|
enum cea_speaker_placement {
|
|
|
|
FL = (1 << 0), /* Front Left */
|
|
|
|
FC = (1 << 1), /* Front Center */
|
|
|
|
FR = (1 << 2), /* Front Right */
|
|
|
|
FLC = (1 << 3), /* Front Left Center */
|
|
|
|
FRC = (1 << 4), /* Front Right Center */
|
|
|
|
RL = (1 << 5), /* Rear Left */
|
|
|
|
RC = (1 << 6), /* Rear Center */
|
|
|
|
RR = (1 << 7), /* Rear Right */
|
|
|
|
RLC = (1 << 8), /* Rear Left Center */
|
|
|
|
RRC = (1 << 9), /* Rear Right Center */
|
|
|
|
LFE = (1 << 10), /* Low Frequency Effect */
|
|
|
|
FLW = (1 << 11), /* Front Left Wide */
|
|
|
|
FRW = (1 << 12), /* Front Right Wide */
|
|
|
|
FLH = (1 << 13), /* Front Left High */
|
|
|
|
FCH = (1 << 14), /* Front Center High */
|
|
|
|
FRH = (1 << 15), /* Front Right High */
|
|
|
|
TC = (1 << 16), /* Top Center */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ELD SA bits in the CEA Speaker Allocation data block
|
|
|
|
*/
|
|
|
|
static int eld_speaker_allocation_bits[] = {
|
|
|
|
[0] = FL | FR,
|
|
|
|
[1] = LFE,
|
|
|
|
[2] = FC,
|
|
|
|
[3] = RL | RR,
|
|
|
|
[4] = RC,
|
|
|
|
[5] = FLC | FRC,
|
|
|
|
[6] = RLC | RRC,
|
|
|
|
/* the following are not defined in ELD yet */
|
|
|
|
[7] = FLW | FRW,
|
|
|
|
[8] = FLH | FRH,
|
|
|
|
[9] = TC,
|
|
|
|
[10] = FCH,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct cea_channel_speaker_allocation {
|
|
|
|
int ca_index;
|
|
|
|
int speakers[8];
|
|
|
|
|
|
|
|
/* derived values, just for convenience */
|
|
|
|
int channels;
|
|
|
|
int spk_mask;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ALSA sequence is:
|
|
|
|
*
|
|
|
|
* surround40 surround41 surround50 surround51 surround71
|
|
|
|
* ch0 front left = = = =
|
|
|
|
* ch1 front right = = = =
|
|
|
|
* ch2 rear left = = = =
|
|
|
|
* ch3 rear right = = = =
|
|
|
|
* ch4 LFE center center center
|
|
|
|
* ch5 LFE LFE
|
|
|
|
* ch6 side left
|
|
|
|
* ch7 side right
|
|
|
|
*
|
|
|
|
* surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
|
|
|
|
*/
|
|
|
|
static int hdmi_channel_mapping[0x32][8] = {
|
|
|
|
/* stereo */
|
|
|
|
[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
|
|
|
|
/* 2.1 */
|
|
|
|
[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
|
|
|
|
/* Dolby Surround */
|
|
|
|
[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
|
|
|
|
/* surround40 */
|
|
|
|
[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
|
|
|
|
/* 4ch */
|
|
|
|
[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
|
|
|
|
/* surround41 */
|
2010-09-21 14:44:51 +08:00
|
|
|
[0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 },
|
2010-03-08 10:44:23 +08:00
|
|
|
/* surround50 */
|
|
|
|
[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
|
|
|
|
/* surround51 */
|
|
|
|
[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
|
|
|
|
/* 7.1 */
|
|
|
|
[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is an ordered list!
|
|
|
|
*
|
|
|
|
* The preceding ones have better chances to be selected by
|
2010-09-21 14:25:49 +08:00
|
|
|
* hdmi_channel_allocation().
|
2010-03-08 10:44:23 +08:00
|
|
|
*/
|
|
|
|
static struct cea_channel_speaker_allocation channel_allocations[] = {
|
|
|
|
/* channel: 7 6 5 4 3 2 1 0 */
|
|
|
|
{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
|
|
|
|
/* 2.1 */
|
|
|
|
{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
|
|
|
|
/* Dolby Surround */
|
|
|
|
{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
|
|
|
|
/* surround40 */
|
|
|
|
{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
|
|
|
|
/* surround41 */
|
|
|
|
{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
|
|
|
|
/* surround50 */
|
|
|
|
{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
|
|
|
|
/* surround51 */
|
|
|
|
{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
/* 6.1 */
|
|
|
|
{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
/* surround71 */
|
|
|
|
{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
|
|
|
|
{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
|
|
|
|
{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HDMI routines
|
|
|
|
*/
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
#define get_pin(spec, idx) \
|
|
|
|
((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx))
|
|
|
|
#define get_cvt(spec, idx) \
|
|
|
|
((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx))
|
|
|
|
#define get_pcm_rec(spec, idx) \
|
|
|
|
((struct hda_pcm *)snd_array_elem(&spec->pcm_rec, idx))
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static int pin_nid_to_pin_index(struct hdmi_spec *spec, hda_nid_t pin_nid)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int pin_idx;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
|
2013-03-13 21:40:31 +08:00
|
|
|
if (get_pin(spec, pin_idx)->pin_nid == pin_nid)
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return pin_idx;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
snd_printk(KERN_WARNING "HDMI: pin nid %d not registered\n", pin_nid);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hinfo_to_pin_index(struct hdmi_spec *spec,
|
|
|
|
struct hda_pcm_stream *hinfo)
|
|
|
|
{
|
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++)
|
2013-03-13 21:40:31 +08:00
|
|
|
if (get_pcm_rec(spec, pin_idx)->stream == hinfo)
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return pin_idx;
|
|
|
|
|
|
|
|
snd_printk(KERN_WARNING "HDMI: hinfo %p not registered\n", hinfo);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid)
|
|
|
|
{
|
|
|
|
int cvt_idx;
|
|
|
|
|
|
|
|
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++)
|
2013-03-13 21:40:31 +08:00
|
|
|
if (get_cvt(spec, cvt_idx)->cvt_nid == cvt_nid)
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return cvt_idx;
|
|
|
|
|
|
|
|
snd_printk(KERN_WARNING "HDMI: cvt nid %d not registered\n", cvt_nid);
|
2010-03-08 10:44:23 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2011-10-01 05:35:41 +08:00
|
|
|
static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
|
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
|
{
|
|
|
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
2013-02-19 23:11:23 +08:00
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-10-18 00:21:12 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
2013-02-19 23:11:23 +08:00
|
|
|
struct hdmi_eld *eld;
|
2011-10-01 05:35:41 +08:00
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
|
|
|
|
|
|
|
|
pin_idx = kcontrol->private_value;
|
2013-10-18 00:21:12 +08:00
|
|
|
per_pin = get_pin(spec, pin_idx);
|
|
|
|
eld = &per_pin->sink_eld;
|
2013-02-19 23:11:23 +08:00
|
|
|
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_lock(&per_pin->lock);
|
2013-02-19 23:11:23 +08:00
|
|
|
uinfo->count = eld->eld_valid ? eld->eld_size : 0;
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
2011-10-01 05:35:41 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
{
|
|
|
|
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
2013-02-19 23:11:23 +08:00
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-10-18 00:21:12 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
2013-02-19 23:11:23 +08:00
|
|
|
struct hdmi_eld *eld;
|
2011-10-01 05:35:41 +08:00
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
pin_idx = kcontrol->private_value;
|
2013-10-18 00:21:12 +08:00
|
|
|
per_pin = get_pin(spec, pin_idx);
|
|
|
|
eld = &per_pin->sink_eld;
|
2013-02-19 23:11:23 +08:00
|
|
|
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_lock(&per_pin->lock);
|
2013-02-19 23:11:23 +08:00
|
|
|
if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
2013-02-19 23:11:23 +08:00
|
|
|
snd_BUG();
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(ucontrol->value.bytes.data, 0,
|
|
|
|
ARRAY_SIZE(ucontrol->value.bytes.data));
|
|
|
|
if (eld->eld_valid)
|
|
|
|
memcpy(ucontrol->value.bytes.data, eld->eld_buffer,
|
|
|
|
eld->eld_size);
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
2011-10-01 05:35:41 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct snd_kcontrol_new eld_bytes_ctl = {
|
|
|
|
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
|
|
|
|
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
|
|
|
|
.name = "ELD",
|
|
|
|
.info = hdmi_eld_ctl_info,
|
|
|
|
.get = hdmi_eld_ctl_get,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
|
|
|
|
int device)
|
|
|
|
{
|
|
|
|
struct snd_kcontrol *kctl;
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
|
|
|
|
if (!kctl)
|
|
|
|
return -ENOMEM;
|
|
|
|
kctl->private_value = pin_idx;
|
|
|
|
kctl->id.device = device;
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl);
|
2011-10-01 05:35:41 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
get_pin(spec, pin_idx)->eld_ctl = kctl;
|
2011-10-01 05:35:41 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
#ifdef BE_PARANOID
|
|
|
|
static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
|
|
|
|
int *packet_index, int *byte_index)
|
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
|
|
|
val = snd_hda_codec_read(codec, pin_nid, 0,
|
|
|
|
AC_VERB_GET_HDMI_DIP_INDEX, 0);
|
|
|
|
|
|
|
|
*packet_index = val >> 5;
|
|
|
|
*byte_index = val & 0x1f;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
|
|
|
|
int packet_index, int byte_index)
|
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
|
|
|
val = (packet_index << 5) | (byte_index & 0x1f);
|
|
|
|
|
|
|
|
snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
|
|
|
|
unsigned char val)
|
|
|
|
{
|
|
|
|
snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
|
|
|
|
}
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static void hdmi_init_pin(struct hda_codec *codec, hda_nid_t pin_nid)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
|
|
|
/* Unmute */
|
|
|
|
if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
|
|
|
|
snd_hda_codec_write(codec, pin_nid, 0,
|
|
|
|
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
|
2012-12-14 17:22:35 +08:00
|
|
|
/* Enable pin out: some machines with GM965 gets broken output when
|
|
|
|
* the pin is disabled or changed while using with HDMI
|
|
|
|
*/
|
2010-03-08 10:44:23 +08:00
|
|
|
snd_hda_codec_write(codec, pin_nid, 0,
|
2012-12-14 17:22:35 +08:00
|
|
|
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t cvt_nid)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return 1 + snd_hda_codec_read(codec, cvt_nid, 0,
|
2010-03-08 10:44:23 +08:00
|
|
|
AC_VERB_GET_CVT_CHAN_COUNT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_set_channel_count(struct hda_codec *codec,
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hda_nid_t cvt_nid, int chs)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
if (chs != hdmi_get_channel_count(codec, cvt_nid))
|
|
|
|
snd_hda_codec_write(codec, cvt_nid, 0,
|
2010-03-08 10:44:23 +08:00
|
|
|
AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
|
|
|
|
}
|
|
|
|
|
2013-10-18 00:21:12 +08:00
|
|
|
/*
|
|
|
|
* ELD proc files
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
static void print_eld_info(struct snd_info_entry *entry,
|
|
|
|
struct snd_info_buffer *buffer)
|
|
|
|
{
|
|
|
|
struct hdmi_spec_per_pin *per_pin = entry->private_data;
|
|
|
|
|
|
|
|
mutex_lock(&per_pin->lock);
|
|
|
|
snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer);
|
|
|
|
mutex_unlock(&per_pin->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_eld_info(struct snd_info_entry *entry,
|
|
|
|
struct snd_info_buffer *buffer)
|
|
|
|
{
|
|
|
|
struct hdmi_spec_per_pin *per_pin = entry->private_data;
|
|
|
|
|
|
|
|
mutex_lock(&per_pin->lock);
|
|
|
|
snd_hdmi_write_eld_info(&per_pin->sink_eld, buffer);
|
|
|
|
mutex_unlock(&per_pin->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
|
|
|
|
{
|
|
|
|
char name[32];
|
|
|
|
struct hda_codec *codec = per_pin->codec;
|
|
|
|
struct snd_info_entry *entry;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
snprintf(name, sizeof(name), "eld#%d.%d", codec->addr, index);
|
|
|
|
err = snd_card_proc_new(codec->bus->card, name, &entry);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
snd_info_set_text_ops(entry, per_pin, print_eld_info);
|
|
|
|
entry->c.text.write = write_eld_info;
|
|
|
|
entry->mode |= S_IWUSR;
|
|
|
|
per_pin->proc_entry = entry;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
|
|
|
|
{
|
|
|
|
if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) {
|
|
|
|
snd_device_free(per_pin->codec->bus->card, per_pin->proc_entry);
|
|
|
|
per_pin->proc_entry = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int snd_hda_eld_proc_new(struct hdmi_spec_per_pin *per_pin,
|
|
|
|
int index)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static inline void snd_hda_eld_proc_free(struct hdmi_spec_per_pin *per_pin)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
2010-03-08 10:44:23 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Channel mapping routines
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compute derived values in channel_allocations[].
|
|
|
|
*/
|
|
|
|
static void init_channel_allocations(void)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
struct cea_channel_speaker_allocation *p;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
|
|
|
|
p = channel_allocations + i;
|
|
|
|
p->channels = 0;
|
|
|
|
p->spk_mask = 0;
|
|
|
|
for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
|
|
|
|
if (p->speakers[j]) {
|
|
|
|
p->channels++;
|
|
|
|
p->spk_mask |= p->speakers[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:02:36 +08:00
|
|
|
static int get_channel_allocation_order(int ca)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
|
|
|
|
if (channel_allocations[i].ca_index == ca)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
/*
|
|
|
|
* The transformation takes two steps:
|
|
|
|
*
|
|
|
|
* eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
|
|
|
|
* spk_mask => (channel_allocations[]) => ai->CA
|
|
|
|
*
|
|
|
|
* TODO: it could select the wrong CA from multiple candidates.
|
|
|
|
*/
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
|
|
|
int i;
|
2010-09-21 14:25:49 +08:00
|
|
|
int ca = 0;
|
2010-03-08 10:44:23 +08:00
|
|
|
int spk_mask = 0;
|
|
|
|
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* CA defaults to 0 for basic stereo audio
|
|
|
|
*/
|
|
|
|
if (channels <= 2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* expand ELD's speaker allocation mask
|
|
|
|
*
|
|
|
|
* ELD tells the speaker mask in a compact(paired) form,
|
|
|
|
* expand ELD's notions to match the ones used by Audio InfoFrame.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
|
2013-02-19 23:11:24 +08:00
|
|
|
if (eld->info.spk_alloc & (1 << i))
|
2010-03-08 10:44:23 +08:00
|
|
|
spk_mask |= eld_speaker_allocation_bits[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* search for the first working match in the CA table */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
|
|
|
|
if (channels == channel_allocations[i].channels &&
|
|
|
|
(spk_mask & channel_allocations[i].spk_mask) ==
|
|
|
|
channel_allocations[i].spk_mask) {
|
2010-09-21 14:25:49 +08:00
|
|
|
ca = channel_allocations[i].ca_index;
|
2010-03-08 10:44:23 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-01 19:36:47 +08:00
|
|
|
if (!ca) {
|
|
|
|
/* if there was no match, select the regular ALSA channel
|
|
|
|
* allocation with the matching number of channels */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
|
|
|
|
if (channels == channel_allocations[i].channels) {
|
|
|
|
ca = channel_allocations[i].ca_index;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 23:11:24 +08:00
|
|
|
snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
|
2010-03-08 10:45:38 +08:00
|
|
|
snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
|
2010-09-21 14:25:49 +08:00
|
|
|
ca, channels, buf);
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2010-09-21 14:25:49 +08:00
|
|
|
return ca;
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_debug_channel_mapping(struct hda_codec *codec,
|
|
|
|
hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
|
|
int i;
|
|
|
|
int slot;
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
slot = snd_hda_codec_read(codec, pin_nid, 0,
|
|
|
|
AC_VERB_GET_HDMI_CHAN_SLOT, i);
|
|
|
|
printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
|
|
|
|
slot >> 4, slot & 0xf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-31 17:36:00 +08:00
|
|
|
static void hdmi_std_setup_channel_mapping(struct hda_codec *codec,
|
2010-03-08 10:44:23 +08:00
|
|
|
hda_nid_t pin_nid,
|
2012-09-06 10:02:37 +08:00
|
|
|
bool non_pcm,
|
2010-09-21 14:25:49 +08:00
|
|
|
int ca)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
2013-10-05 07:25:39 +08:00
|
|
|
struct cea_channel_speaker_allocation *ch_alloc;
|
2010-03-08 10:44:23 +08:00
|
|
|
int i;
|
|
|
|
int err;
|
2012-09-06 10:02:36 +08:00
|
|
|
int order;
|
2012-09-06 10:02:37 +08:00
|
|
|
int non_pcm_mapping[8];
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2012-09-06 10:02:36 +08:00
|
|
|
order = get_channel_allocation_order(ca);
|
2013-10-05 07:25:39 +08:00
|
|
|
ch_alloc = &channel_allocations[order];
|
2012-09-06 10:02:37 +08:00
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
if (hdmi_channel_mapping[ca][1] == 0) {
|
2013-10-05 07:25:39 +08:00
|
|
|
int hdmi_slot = 0;
|
|
|
|
/* fill actual channel mappings in ALSA channel (i) order */
|
|
|
|
for (i = 0; i < ch_alloc->channels; i++) {
|
|
|
|
while (!ch_alloc->speakers[7 - hdmi_slot] && !WARN_ON(hdmi_slot >= 8))
|
|
|
|
hdmi_slot++; /* skip zero slots */
|
|
|
|
|
|
|
|
hdmi_channel_mapping[ca][i] = (i << 4) | hdmi_slot++;
|
|
|
|
}
|
|
|
|
/* fill the rest of the slots with ALSA channel 0xf */
|
|
|
|
for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++)
|
|
|
|
if (!ch_alloc->speakers[7 - hdmi_slot])
|
|
|
|
hdmi_channel_mapping[ca][i++] = (0xf << 4) | hdmi_slot;
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
2012-09-06 10:02:37 +08:00
|
|
|
if (non_pcm) {
|
2013-10-05 07:25:39 +08:00
|
|
|
for (i = 0; i < ch_alloc->channels; i++)
|
2013-10-05 07:25:41 +08:00
|
|
|
non_pcm_mapping[i] = (i << 4) | i;
|
2012-09-06 10:02:37 +08:00
|
|
|
for (; i < 8; i++)
|
2013-10-05 07:25:41 +08:00
|
|
|
non_pcm_mapping[i] = (0xf << 4) | i;
|
2012-09-06 10:02:37 +08:00
|
|
|
}
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
err = snd_hda_codec_write(codec, pin_nid, 0,
|
|
|
|
AC_VERB_SET_HDMI_CHAN_SLOT,
|
2012-09-06 10:02:37 +08:00
|
|
|
non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]);
|
2010-03-08 10:44:23 +08:00
|
|
|
if (err) {
|
2010-03-08 10:45:38 +08:00
|
|
|
snd_printdd(KERN_NOTICE
|
|
|
|
"HDMI: channel mapping failed\n");
|
2010-03-08 10:44:23 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 17:36:00 +08:00
|
|
|
struct channel_map_table {
|
|
|
|
unsigned char map; /* ALSA API channel map position */
|
|
|
|
int spk_mask; /* speaker position bit mask */
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct channel_map_table map_tables[] = {
|
2013-10-05 07:25:42 +08:00
|
|
|
{ SNDRV_CHMAP_FL, FL },
|
|
|
|
{ SNDRV_CHMAP_FR, FR },
|
|
|
|
{ SNDRV_CHMAP_RL, RL },
|
|
|
|
{ SNDRV_CHMAP_RR, RR },
|
|
|
|
{ SNDRV_CHMAP_LFE, LFE },
|
|
|
|
{ SNDRV_CHMAP_FC, FC },
|
|
|
|
{ SNDRV_CHMAP_RLC, RLC },
|
|
|
|
{ SNDRV_CHMAP_RRC, RRC },
|
|
|
|
{ SNDRV_CHMAP_RC, RC },
|
|
|
|
{ SNDRV_CHMAP_FLC, FLC },
|
|
|
|
{ SNDRV_CHMAP_FRC, FRC },
|
|
|
|
{ SNDRV_CHMAP_FLH, FLH },
|
|
|
|
{ SNDRV_CHMAP_FRH, FRH },
|
|
|
|
{ SNDRV_CHMAP_FLW, FLW },
|
|
|
|
{ SNDRV_CHMAP_FRW, FRW },
|
|
|
|
{ SNDRV_CHMAP_TC, TC },
|
|
|
|
{ SNDRV_CHMAP_FCH, FCH },
|
2012-07-31 17:36:00 +08:00
|
|
|
{} /* terminator */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* from ALSA API channel position to speaker bit mask */
|
|
|
|
static int to_spk_mask(unsigned char c)
|
|
|
|
{
|
|
|
|
struct channel_map_table *t = map_tables;
|
|
|
|
for (; t->map; t++) {
|
|
|
|
if (t->map == c)
|
|
|
|
return t->spk_mask;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* from ALSA API channel position to CEA slot */
|
2013-10-05 07:25:42 +08:00
|
|
|
static int to_cea_slot(int ordered_ca, unsigned char pos)
|
2012-07-31 17:36:00 +08:00
|
|
|
{
|
2013-10-05 07:25:42 +08:00
|
|
|
int mask = to_spk_mask(pos);
|
|
|
|
int i;
|
2012-07-31 17:36:00 +08:00
|
|
|
|
2013-10-05 07:25:42 +08:00
|
|
|
if (mask) {
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
if (channel_allocations[ordered_ca].speakers[7 - i] == mask)
|
|
|
|
return i;
|
|
|
|
}
|
2012-07-31 17:36:00 +08:00
|
|
|
}
|
2013-10-05 07:25:42 +08:00
|
|
|
|
|
|
|
return -1;
|
2012-07-31 17:36:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* from speaker bit mask to ALSA API channel position */
|
|
|
|
static int spk_to_chmap(int spk)
|
|
|
|
{
|
|
|
|
struct channel_map_table *t = map_tables;
|
|
|
|
for (; t->map; t++) {
|
|
|
|
if (t->spk_mask == spk)
|
|
|
|
return t->map;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-10-05 07:25:42 +08:00
|
|
|
/* from CEA slot to ALSA API channel position */
|
|
|
|
static int from_cea_slot(int ordered_ca, unsigned char slot)
|
|
|
|
{
|
|
|
|
int mask = channel_allocations[ordered_ca].speakers[7 - slot];
|
|
|
|
|
|
|
|
return spk_to_chmap(mask);
|
|
|
|
}
|
|
|
|
|
2012-07-31 17:36:00 +08:00
|
|
|
/* get the CA index corresponding to the given ALSA API channel map */
|
|
|
|
static int hdmi_manual_channel_allocation(int chs, unsigned char *map)
|
|
|
|
{
|
|
|
|
int i, spks = 0, spk_mask = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < chs; i++) {
|
|
|
|
int mask = to_spk_mask(map[i]);
|
|
|
|
if (mask) {
|
|
|
|
spk_mask |= mask;
|
|
|
|
spks++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
|
|
|
|
if ((chs == channel_allocations[i].channels ||
|
|
|
|
spks == channel_allocations[i].channels) &&
|
|
|
|
(spk_mask & channel_allocations[i].spk_mask) ==
|
|
|
|
channel_allocations[i].spk_mask)
|
|
|
|
return channel_allocations[i].ca_index;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set up the channel slots for the given ALSA API channel map */
|
|
|
|
static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec,
|
|
|
|
hda_nid_t pin_nid,
|
2013-10-05 07:25:42 +08:00
|
|
|
int chs, unsigned char *map,
|
|
|
|
int ca)
|
2012-07-31 17:36:00 +08:00
|
|
|
{
|
2013-10-05 07:25:42 +08:00
|
|
|
int ordered_ca = get_channel_allocation_order(ca);
|
2013-10-05 07:25:41 +08:00
|
|
|
int alsa_pos, hdmi_slot;
|
|
|
|
int assignments[8] = {[0 ... 7] = 0xf};
|
|
|
|
|
|
|
|
for (alsa_pos = 0; alsa_pos < chs; alsa_pos++) {
|
|
|
|
|
2013-10-05 07:25:42 +08:00
|
|
|
hdmi_slot = to_cea_slot(ordered_ca, map[alsa_pos]);
|
2013-10-05 07:25:41 +08:00
|
|
|
|
|
|
|
if (hdmi_slot < 0)
|
|
|
|
continue; /* unassigned channel */
|
|
|
|
|
|
|
|
assignments[hdmi_slot] = alsa_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (hdmi_slot = 0; hdmi_slot < 8; hdmi_slot++) {
|
2012-07-31 17:36:00 +08:00
|
|
|
int val, err;
|
2013-10-05 07:25:41 +08:00
|
|
|
|
|
|
|
val = (assignments[hdmi_slot] << 4) | hdmi_slot;
|
2012-07-31 17:36:00 +08:00
|
|
|
err = snd_hda_codec_write(codec, pin_nid, 0,
|
|
|
|
AC_VERB_SET_HDMI_CHAN_SLOT, val);
|
|
|
|
if (err)
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* store ALSA API channel map from the current default map */
|
|
|
|
static void hdmi_setup_fake_chmap(unsigned char *map, int ca)
|
|
|
|
{
|
|
|
|
int i;
|
ALSA: hda - hdmi: Fix reported channel map on common default layouts
hdmi_setup_fake_chmap() is supposed to set the reported channel map when
the channel map is not specified by the user.
However, the function indexes channel_allocations[] with a wrong value
and extracts the wrong nibble from hdmi_channel_mapping[], causing wrong
channel maps to be shown.
Fix those issues.
Tested on Intel HDMI to correctly generate various channel maps, for
example 3,4,14,15,7,8,5,6 (instead of incorrect 3,4,8,7,5,6,14,0) for
standard 7.1 channel audio. (Note that the side and rear channels are
reported as RL/RR and RLC/RRC, respectively, as per the CEA-861
standard, instead of the more traditional SL/SR and RL/RR.)
Note that this only fixes the layouts that only contain traditional 7.1
speakers (2.0, 2.1, 4.0, 5.1, 7.1, etc.). E.g. the rear center of 6.1
is still being shown wrongly due to an issue with from_cea_slot()
which will be fixed in a later patch.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:38 +08:00
|
|
|
int ordered_ca = get_channel_allocation_order(ca);
|
2012-07-31 17:36:00 +08:00
|
|
|
for (i = 0; i < 8; i++) {
|
ALSA: hda - hdmi: Fix reported channel map on common default layouts
hdmi_setup_fake_chmap() is supposed to set the reported channel map when
the channel map is not specified by the user.
However, the function indexes channel_allocations[] with a wrong value
and extracts the wrong nibble from hdmi_channel_mapping[], causing wrong
channel maps to be shown.
Fix those issues.
Tested on Intel HDMI to correctly generate various channel maps, for
example 3,4,14,15,7,8,5,6 (instead of incorrect 3,4,8,7,5,6,14,0) for
standard 7.1 channel audio. (Note that the side and rear channels are
reported as RL/RR and RLC/RRC, respectively, as per the CEA-861
standard, instead of the more traditional SL/SR and RL/RR.)
Note that this only fixes the layouts that only contain traditional 7.1
speakers (2.0, 2.1, 4.0, 5.1, 7.1, etc.). E.g. the rear center of 6.1
is still being shown wrongly due to an issue with from_cea_slot()
which will be fixed in a later patch.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:38 +08:00
|
|
|
if (i < channel_allocations[ordered_ca].channels)
|
2013-10-05 07:25:42 +08:00
|
|
|
map[i] = from_cea_slot(ordered_ca, hdmi_channel_mapping[ca][i] & 0x0f);
|
2012-07-31 17:36:00 +08:00
|
|
|
else
|
|
|
|
map[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_setup_channel_mapping(struct hda_codec *codec,
|
|
|
|
hda_nid_t pin_nid, bool non_pcm, int ca,
|
2013-02-03 23:55:45 +08:00
|
|
|
int channels, unsigned char *map,
|
|
|
|
bool chmap_set)
|
2012-07-31 17:36:00 +08:00
|
|
|
{
|
2013-02-03 23:55:45 +08:00
|
|
|
if (!non_pcm && chmap_set) {
|
2012-07-31 17:36:00 +08:00
|
|
|
hdmi_manual_setup_channel_mapping(codec, pin_nid,
|
2013-10-05 07:25:42 +08:00
|
|
|
channels, map, ca);
|
2012-07-31 17:36:00 +08:00
|
|
|
} else {
|
|
|
|
hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca);
|
|
|
|
hdmi_setup_fake_chmap(map, ca);
|
|
|
|
}
|
2013-10-05 07:25:44 +08:00
|
|
|
|
|
|
|
hdmi_debug_channel_mapping(codec, pin_nid);
|
2012-07-31 17:36:00 +08:00
|
|
|
}
|
2010-03-08 10:44:23 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Audio InfoFrame routines
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Enable Audio InfoFrame Transmission
|
|
|
|
*/
|
|
|
|
static void hdmi_start_infoframe_trans(struct hda_codec *codec,
|
|
|
|
hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
|
|
|
|
snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
|
|
|
|
AC_DIPXMIT_BEST);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable Audio InfoFrame Transmission
|
|
|
|
*/
|
|
|
|
static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
|
|
|
|
hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
|
|
|
|
snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
|
|
|
|
AC_DIPXMIT_DISABLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
|
|
|
int i;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
size = snd_hdmi_get_eld_size(codec, pin_nid);
|
|
|
|
printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
size = snd_hda_codec_read(codec, pin_nid, 0,
|
|
|
|
AC_VERB_GET_HDMI_DIP_SIZE, i);
|
|
|
|
printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
#ifdef BE_PARANOID
|
|
|
|
int i, j;
|
|
|
|
int size;
|
|
|
|
int pi, bi;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
|
size = snd_hda_codec_read(codec, pin_nid, 0,
|
|
|
|
AC_VERB_GET_HDMI_DIP_SIZE, i);
|
|
|
|
if (size == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
hdmi_set_dip_index(codec, pin_nid, i, 0x0);
|
|
|
|
for (j = 1; j < 1000; j++) {
|
|
|
|
hdmi_write_dip_byte(codec, pin_nid, 0x0);
|
|
|
|
hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
|
|
|
|
if (pi != i)
|
|
|
|
snd_printd(KERN_INFO "dip index %d: %d != %d\n",
|
|
|
|
bi, pi, i);
|
|
|
|
if (bi == 0) /* byte index wrapped around */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
snd_printd(KERN_INFO
|
|
|
|
"HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
|
|
|
|
i, size, j);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-09-21 14:25:49 +08:00
|
|
|
static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
2010-09-21 14:25:49 +08:00
|
|
|
u8 *bytes = (u8 *)hdmi_ai;
|
2010-03-08 10:44:23 +08:00
|
|
|
u8 sum = 0;
|
|
|
|
int i;
|
|
|
|
|
2010-09-21 14:25:49 +08:00
|
|
|
hdmi_ai->checksum = 0;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2010-09-21 14:25:49 +08:00
|
|
|
for (i = 0; i < sizeof(*hdmi_ai); i++)
|
2010-03-08 10:44:23 +08:00
|
|
|
sum += bytes[i];
|
|
|
|
|
2010-09-21 14:25:49 +08:00
|
|
|
hdmi_ai->checksum = -sum;
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
|
|
|
|
hda_nid_t pin_nid,
|
2010-09-21 14:25:49 +08:00
|
|
|
u8 *dip, int size)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
hdmi_debug_dip_size(codec, pin_nid);
|
|
|
|
hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
|
|
|
|
|
|
|
|
hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
|
2010-09-21 14:25:49 +08:00
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
hdmi_write_dip_byte(codec, pin_nid, dip[i]);
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
|
2010-09-21 14:25:49 +08:00
|
|
|
u8 *dip, int size)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
|
|
|
u8 val;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
|
|
|
|
!= AC_DIPXMIT_BEST)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
|
2010-09-21 14:25:49 +08:00
|
|
|
for (i = 0; i < size; i++) {
|
2010-03-08 10:44:23 +08:00
|
|
|
val = snd_hda_codec_read(codec, pin_nid, 0,
|
|
|
|
AC_VERB_GET_HDMI_DIP_DATA, 0);
|
2010-09-21 14:25:49 +08:00
|
|
|
if (val != dip[i])
|
2010-03-08 10:44:23 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-02 18:33:02 +08:00
|
|
|
static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
|
|
|
|
struct hdmi_spec_per_pin *per_pin,
|
|
|
|
bool non_pcm)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
2013-09-02 18:33:02 +08:00
|
|
|
int channels = per_pin->channels;
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
int active_channels;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_eld *eld;
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
int ca, ordered_ca;
|
2011-02-11 19:17:30 +08:00
|
|
|
union audio_infoframe ai;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2013-09-02 18:33:02 +08:00
|
|
|
if (!channels)
|
|
|
|
return;
|
|
|
|
|
2013-09-05 04:37:12 +08:00
|
|
|
if (is_haswell(codec))
|
|
|
|
snd_hda_codec_write(codec, pin_nid, 0,
|
|
|
|
AC_VERB_SET_AMP_GAIN_MUTE,
|
|
|
|
AMP_OUT_UNMUTE);
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
eld = &per_pin->sink_eld;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
if (!eld->monitor_present)
|
|
|
|
return;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2012-07-31 17:36:00 +08:00
|
|
|
if (!non_pcm && per_pin->chmap_set)
|
|
|
|
ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
|
|
|
|
else
|
|
|
|
ca = hdmi_channel_allocation(eld, channels);
|
|
|
|
if (ca < 0)
|
|
|
|
ca = 0;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
ordered_ca = get_channel_allocation_order(ca);
|
|
|
|
active_channels = channel_allocations[ordered_ca].channels;
|
|
|
|
|
|
|
|
hdmi_set_channel_count(codec, per_pin->cvt_nid, active_channels);
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
memset(&ai, 0, sizeof(ai));
|
2013-02-19 23:11:24 +08:00
|
|
|
if (eld->info.conn_type == 0) { /* HDMI */
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
|
|
|
|
|
|
|
|
hdmi_ai->type = 0x84;
|
|
|
|
hdmi_ai->ver = 0x01;
|
|
|
|
hdmi_ai->len = 0x0a;
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
hdmi_ai->CC02_CT47 = active_channels - 1;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hdmi_ai->CA = ca;
|
|
|
|
hdmi_checksum_audio_infoframe(hdmi_ai);
|
2013-02-19 23:11:24 +08:00
|
|
|
} else if (eld->info.conn_type == 1) { /* DisplayPort */
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct dp_audio_infoframe *dp_ai = &ai.dp;
|
|
|
|
|
|
|
|
dp_ai->type = 0x84;
|
|
|
|
dp_ai->len = 0x1b;
|
|
|
|
dp_ai->ver = 0x11 << 2;
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
dp_ai->CC02_CT47 = active_channels - 1;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
dp_ai->CA = ca;
|
|
|
|
} else {
|
|
|
|
snd_printd("HDMI: unknown connection type at pin %d\n",
|
|
|
|
pin_nid);
|
|
|
|
return;
|
|
|
|
}
|
2010-09-21 14:25:49 +08:00
|
|
|
|
2013-10-08 00:24:52 +08:00
|
|
|
/*
|
|
|
|
* always configure channel mapping, it may have been changed by the
|
|
|
|
* user in the meantime
|
|
|
|
*/
|
|
|
|
hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca,
|
|
|
|
channels, per_pin->chmap,
|
|
|
|
per_pin->chmap_set);
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
/*
|
|
|
|
* sizeof(ai) is used instead of sizeof(*hdmi_ai) or
|
|
|
|
* sizeof(*dp_ai) to avoid partial match/update problems when
|
|
|
|
* the user switches between HDMI/DP monitors.
|
|
|
|
*/
|
|
|
|
if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
|
|
|
|
sizeof(ai))) {
|
|
|
|
snd_printdd("hdmi_setup_audio_infoframe: "
|
2013-10-05 07:25:44 +08:00
|
|
|
"pin=%d channels=%d ca=0x%02x\n",
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
pin_nid,
|
2013-10-05 07:25:44 +08:00
|
|
|
active_channels, ca);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hdmi_stop_infoframe_trans(codec, pin_nid);
|
|
|
|
hdmi_fill_audio_infoframe(codec, pin_nid,
|
|
|
|
ai.bytes, sizeof(ai));
|
|
|
|
hdmi_start_infoframe_trans(codec, pin_nid);
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
2012-09-06 10:02:37 +08:00
|
|
|
|
2012-09-06 23:42:08 +08:00
|
|
|
per_pin->non_pcm = non_pcm;
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unsolicited events
|
|
|
|
*/
|
|
|
|
|
2011-11-19 06:59:32 +08:00
|
|
|
static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
|
2010-07-28 20:21:55 +08:00
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2011-10-28 07:16:55 +08:00
|
|
|
int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
|
|
|
|
int pin_nid;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int pin_idx;
|
2011-10-28 07:16:55 +08:00
|
|
|
struct hda_jack_tbl *jack;
|
2013-08-27 09:35:49 +08:00
|
|
|
int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
|
2011-10-28 07:16:55 +08:00
|
|
|
|
|
|
|
jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
|
|
|
|
if (!jack)
|
|
|
|
return;
|
|
|
|
pin_nid = jack->nid;
|
|
|
|
jack->jack_dirty = 1;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2012-04-10 17:00:35 +08:00
|
|
|
_snd_printd(SND_PR_VERBOSE,
|
2013-08-27 09:35:49 +08:00
|
|
|
"HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n",
|
|
|
|
codec->addr, pin_nid, dev_entry, !!(res & AC_UNSOL_RES_IA),
|
2012-04-10 17:00:35 +08:00
|
|
|
!!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV));
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
pin_idx = pin_nid_to_pin_index(spec, pin_nid);
|
|
|
|
if (pin_idx < 0)
|
2010-03-08 10:44:23 +08:00
|
|
|
return;
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
hdmi_present_sense(get_pin(spec, pin_idx), 1);
|
2011-10-28 06:03:22 +08:00
|
|
|
snd_hda_jack_report_sync(codec);
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
|
|
|
|
{
|
|
|
|
int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
|
|
|
|
int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
|
|
|
|
int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
|
|
|
|
int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
|
|
|
|
|
|
|
|
printk(KERN_INFO
|
2012-06-21 17:41:05 +08:00
|
|
|
"HDMI CP event: CODEC=%d TAG=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
codec->addr,
|
2010-03-08 10:44:23 +08:00
|
|
|
tag,
|
|
|
|
subtag,
|
|
|
|
cp_state,
|
|
|
|
cp_ready);
|
|
|
|
|
|
|
|
/* TODO */
|
|
|
|
if (cp_state)
|
|
|
|
;
|
|
|
|
if (cp_ready)
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
|
|
|
|
{
|
|
|
|
int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
|
|
|
|
int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
|
|
|
|
|
2011-10-28 07:16:55 +08:00
|
|
|
if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) {
|
2010-03-08 10:44:23 +08:00
|
|
|
snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (subtag == 0)
|
|
|
|
hdmi_intrinsic_event(codec, res);
|
|
|
|
else
|
|
|
|
hdmi_non_intrinsic_event(codec, res);
|
|
|
|
}
|
|
|
|
|
2013-09-05 04:37:12 +08:00
|
|
|
static void haswell_verify_D0(struct hda_codec *codec,
|
2013-06-18 10:41:53 +08:00
|
|
|
hda_nid_t cvt_nid, hda_nid_t nid)
|
2013-04-10 18:26:07 +08:00
|
|
|
{
|
2013-09-05 04:37:12 +08:00
|
|
|
int pwr;
|
2013-04-10 18:26:07 +08:00
|
|
|
|
2013-06-18 10:41:53 +08:00
|
|
|
/* For Haswell, the converter 1/2 may keep in D3 state after bootup,
|
|
|
|
* thus pins could only choose converter 0 for use. Make sure the
|
|
|
|
* converters are in correct power state */
|
2013-06-18 22:28:36 +08:00
|
|
|
if (!snd_hda_check_power_state(codec, cvt_nid, AC_PWRST_D0))
|
2013-06-18 10:41:53 +08:00
|
|
|
snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
|
|
|
|
|
2013-06-18 22:28:36 +08:00
|
|
|
if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0)) {
|
2013-04-10 18:26:07 +08:00
|
|
|
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE,
|
|
|
|
AC_PWRST_D0);
|
|
|
|
msleep(40);
|
|
|
|
pwr = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
|
|
|
|
pwr = (pwr & AC_PWRST_ACTUAL) >> AC_PWRST_ACTUAL_SHIFT;
|
|
|
|
snd_printd("Haswell HDMI audio: Power for pin 0x%x is now D%d\n", nid, pwr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
/*
|
|
|
|
* Callbacks
|
|
|
|
*/
|
|
|
|
|
2010-08-03 20:21:00 +08:00
|
|
|
/* HBR should be Non-PCM, 8 channels */
|
|
|
|
#define is_hbr_format(format) \
|
|
|
|
((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7)
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
|
|
|
|
hda_nid_t pin_nid, u32 stream_tag, int format)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
2010-08-03 18:28:58 +08:00
|
|
|
int pinctl;
|
|
|
|
int new_pinctl = 0;
|
|
|
|
|
2013-09-05 04:36:57 +08:00
|
|
|
if (is_haswell(codec))
|
2013-09-05 04:37:12 +08:00
|
|
|
haswell_verify_D0(codec, cvt_nid, pin_nid);
|
2013-04-10 18:26:07 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) {
|
|
|
|
pinctl = snd_hda_codec_read(codec, pin_nid, 0,
|
2010-08-03 18:28:58 +08:00
|
|
|
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
|
|
|
|
|
|
|
new_pinctl = pinctl & ~AC_PINCTL_EPT;
|
2010-08-03 20:21:00 +08:00
|
|
|
if (is_hbr_format(format))
|
2010-08-03 18:28:58 +08:00
|
|
|
new_pinctl |= AC_PINCTL_EPT_HBR;
|
|
|
|
else
|
|
|
|
new_pinctl |= AC_PINCTL_EPT_NATIVE;
|
|
|
|
|
|
|
|
snd_printdd("hdmi_setup_stream: "
|
|
|
|
"NID=0x%x, %spinctl=0x%x\n",
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
pin_nid,
|
2010-08-03 18:28:58 +08:00
|
|
|
pinctl == new_pinctl ? "" : "new-",
|
|
|
|
new_pinctl);
|
|
|
|
|
|
|
|
if (pinctl != new_pinctl)
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
snd_hda_codec_write(codec, pin_nid, 0,
|
2010-08-03 18:28:58 +08:00
|
|
|
AC_VERB_SET_PIN_WIDGET_CONTROL,
|
|
|
|
new_pinctl);
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
}
|
2010-08-03 20:21:00 +08:00
|
|
|
if (is_hbr_format(format) && !new_pinctl) {
|
2010-08-03 18:28:58 +08:00
|
|
|
snd_printdd("hdmi_setup_stream: HBR is not supported\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format);
|
2010-08-03 18:28:58 +08:00
|
|
|
return 0;
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
2013-06-18 21:42:14 +08:00
|
|
|
static int hdmi_choose_cvt(struct hda_codec *codec,
|
|
|
|
int pin_idx, int *cvt_id, int *mux_id)
|
2010-08-13 14:45:23 +08:00
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
|
|
|
struct hdmi_spec_per_cvt *per_cvt = NULL;
|
2013-06-18 21:42:14 +08:00
|
|
|
int cvt_idx, mux_idx = 0;
|
2010-08-13 14:45:23 +08:00
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
per_pin = get_pin(spec, pin_idx);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
|
|
|
/* Dynamically assign converter to stream */
|
|
|
|
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
|
2013-03-13 21:40:31 +08:00
|
|
|
per_cvt = get_cvt(spec, cvt_idx);
|
2010-08-13 14:45:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
/* Must not already be assigned */
|
|
|
|
if (per_cvt->assigned)
|
|
|
|
continue;
|
|
|
|
/* Must be in pin's mux's list of converters */
|
|
|
|
for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++)
|
|
|
|
if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid)
|
|
|
|
break;
|
|
|
|
/* Not in mux list */
|
|
|
|
if (mux_idx == per_pin->num_mux_nids)
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
2013-06-18 21:42:14 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
/* No free converters */
|
|
|
|
if (cvt_idx == spec->num_cvts)
|
|
|
|
return -ENODEV;
|
|
|
|
|
2013-06-18 21:42:14 +08:00
|
|
|
if (cvt_id)
|
|
|
|
*cvt_id = cvt_idx;
|
|
|
|
if (mux_id)
|
|
|
|
*mux_id = mux_idx;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void haswell_config_cvts(struct hda_codec *codec,
|
2013-09-22 08:34:45 +08:00
|
|
|
hda_nid_t pin_nid, int mux_idx)
|
2013-06-18 21:42:14 +08:00
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-09-22 08:34:45 +08:00
|
|
|
hda_nid_t nid, end_nid;
|
|
|
|
int cvt_idx, curr;
|
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
2013-06-18 21:42:14 +08:00
|
|
|
|
2013-09-22 08:34:45 +08:00
|
|
|
/* configure all pins, including "no physical connection" ones */
|
|
|
|
end_nid = codec->start_nid + codec->num_nodes;
|
|
|
|
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
|
|
|
unsigned int wid_caps = get_wcaps(codec, nid);
|
|
|
|
unsigned int wid_type = get_wcaps_type(wid_caps);
|
|
|
|
|
|
|
|
if (wid_type != AC_WID_PIN)
|
|
|
|
continue;
|
2013-06-18 21:42:14 +08:00
|
|
|
|
2013-09-22 08:34:45 +08:00
|
|
|
if (nid == pin_nid)
|
2013-06-18 21:42:14 +08:00
|
|
|
continue;
|
|
|
|
|
2013-09-22 08:34:45 +08:00
|
|
|
curr = snd_hda_codec_read(codec, nid, 0,
|
2013-06-18 21:42:14 +08:00
|
|
|
AC_VERB_GET_CONNECT_SEL, 0);
|
2013-09-22 08:34:45 +08:00
|
|
|
if (curr != mux_idx)
|
|
|
|
continue;
|
2013-06-18 21:42:14 +08:00
|
|
|
|
2013-09-22 08:34:45 +08:00
|
|
|
/* choose an unassigned converter. The conveters in the
|
|
|
|
* connection list are in the same order as in the codec.
|
|
|
|
*/
|
|
|
|
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
|
|
|
|
per_cvt = get_cvt(spec, cvt_idx);
|
|
|
|
if (!per_cvt->assigned) {
|
|
|
|
snd_printdd("choose cvt %d for pin nid %d\n",
|
|
|
|
cvt_idx, nid);
|
|
|
|
snd_hda_codec_write_cache(codec, nid, 0,
|
2013-06-18 21:42:14 +08:00
|
|
|
AC_VERB_SET_CONNECT_SEL,
|
2013-09-22 08:34:45 +08:00
|
|
|
cvt_idx);
|
|
|
|
break;
|
|
|
|
}
|
2013-06-18 21:42:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HDA PCM callbacks
|
|
|
|
*/
|
|
|
|
static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
|
|
int pin_idx, cvt_idx, mux_idx = 0;
|
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
|
|
|
struct hdmi_eld *eld;
|
|
|
|
struct hdmi_spec_per_cvt *per_cvt = NULL;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Validate hinfo */
|
|
|
|
pin_idx = hinfo_to_pin_index(spec, hinfo);
|
|
|
|
if (snd_BUG_ON(pin_idx < 0))
|
|
|
|
return -EINVAL;
|
|
|
|
per_pin = get_pin(spec, pin_idx);
|
|
|
|
eld = &per_pin->sink_eld;
|
|
|
|
|
|
|
|
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
per_cvt = get_cvt(spec, cvt_idx);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
/* Claim converter */
|
|
|
|
per_cvt->assigned = 1;
|
ALSA: hda - hdmi: Fix programmed active channel count
Currently the converter channel count is set to the number of actual
input channels. The audio infoframe channel count field is set
similarly.
However, sometimes the used channel map does not map all input channels
to outputs. Notably, 3 channel modes (e.g. 2.1) require a dummy input
channel so there are 4 input channels. According to the HDA
specification, converter channel count should be programmed according to
the number of _active_ channels.
On Intel HDMI codecs (but not on NVIDIA), setting the converter channel
to a higher value than there are actually mapped channels to HDMI slots
will cause no audio to be output at all.
Note that the effects of this issue are currently partially masked by
other bugs that prevent the driver from actually unmapping channels in
certain cases. For example, if a 4 channel stream is first created and
prepared, it gets a FL,FR,RL,RR mapping (ALSA->HDMI slot mapping 0->0,
1->1, 2->4, 3->5). If one thereafter assigns a FR,FL,FC mapping to it,
the driver will remap 2->3 but fail to unmap 2->4 and 3->5, so there are
still 4 active channels and the issue will not trigger in this case.
These bugs will be fixed separately.
Fix the channel counts in the converter channel count field and in the
audio infoframe channel count field to match the actual number of active
channels.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-10-05 07:25:40 +08:00
|
|
|
per_pin->cvt_nid = per_cvt->cvt_nid;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hinfo->nid = per_cvt->cvt_nid;
|
|
|
|
|
2013-06-18 22:14:22 +08:00
|
|
|
snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
AC_VERB_SET_CONNECT_SEL,
|
|
|
|
mux_idx);
|
2013-06-18 21:42:14 +08:00
|
|
|
|
|
|
|
/* configure unused pins to choose other converters */
|
2013-09-05 04:36:57 +08:00
|
|
|
if (is_haswell(codec))
|
2013-09-22 08:34:45 +08:00
|
|
|
haswell_config_cvts(codec, per_pin->pin_nid, mux_idx);
|
2013-06-18 21:42:14 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
|
2010-08-13 14:45:23 +08:00
|
|
|
|
2011-06-02 01:14:20 +08:00
|
|
|
/* Initially set the converter's capabilities */
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hinfo->channels_min = per_cvt->channels_min;
|
|
|
|
hinfo->channels_max = per_cvt->channels_max;
|
|
|
|
hinfo->rates = per_cvt->rates;
|
|
|
|
hinfo->formats = per_cvt->formats;
|
|
|
|
hinfo->maxbps = per_cvt->maxbps;
|
2011-06-02 01:14:20 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
/* Restrict capabilities by ELD if this isn't disabled */
|
2011-06-02 01:14:16 +08:00
|
|
|
if (!static_hdmi_pcm && eld->eld_valid) {
|
2013-02-19 23:11:24 +08:00
|
|
|
snd_hdmi_eld_update_pcm_info(&eld->info, hinfo);
|
2010-08-13 14:45:23 +08:00
|
|
|
if (hinfo->channels_min > hinfo->channels_max ||
|
2013-02-01 21:01:27 +08:00
|
|
|
!hinfo->rates || !hinfo->formats) {
|
|
|
|
per_cvt->assigned = 0;
|
|
|
|
hinfo->nid = 0;
|
|
|
|
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
2010-08-13 14:45:23 +08:00
|
|
|
return -ENODEV;
|
2013-02-01 21:01:27 +08:00
|
|
|
}
|
2010-08-13 14:45:23 +08:00
|
|
|
}
|
2011-06-02 01:14:20 +08:00
|
|
|
|
|
|
|
/* Store the updated parameters */
|
2011-01-14 17:30:46 +08:00
|
|
|
runtime->hw.channels_min = hinfo->channels_min;
|
|
|
|
runtime->hw.channels_max = hinfo->channels_max;
|
|
|
|
runtime->hw.formats = hinfo->formats;
|
|
|
|
runtime->hw.rates = hinfo->rates;
|
2011-01-14 17:33:26 +08:00
|
|
|
|
|
|
|
snd_pcm_hw_constraint_step(substream->runtime, 0,
|
|
|
|
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
|
2010-08-13 14:45:23 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
/*
|
|
|
|
* HDA/HDMI auto parsing
|
|
|
|
*/
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
|
|
|
if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
|
|
|
|
snd_printk(KERN_WARNING
|
|
|
|
"HDMI: pin %d wcaps %#x "
|
|
|
|
"does not support connection list\n",
|
|
|
|
pin_nid, get_wcaps(codec, pin_nid));
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid,
|
|
|
|
per_pin->mux_nids,
|
|
|
|
HDA_MAX_CONNECTIONS);
|
2010-03-08 10:44:23 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-11-19 06:59:32 +08:00
|
|
|
static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
2011-11-16 16:29:47 +08:00
|
|
|
struct hda_codec *codec = per_pin->codec;
|
2013-02-19 23:11:25 +08:00
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
struct hdmi_eld *eld = &spec->temp_eld;
|
|
|
|
struct hdmi_eld *pin_eld = &per_pin->sink_eld;
|
2011-11-16 16:29:47 +08:00
|
|
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
ALSA: HDA: Unify HDMI hotplug handling.
This change unifies the initial handling of a pin's state with the code to
update a pin's state after a hotplug (unsolicited response) event. The
initial probing, and all updates, are now routed through hdmi_present_sense.
The stored PD and ELDV status is now always derived from GetPinSense verb
execution, and not from the data in the unsolicited response. This means:
a) The WAR for NVIDIA codec's UR.PD values ("old_pin_detect") can be
removed, since this only affected the no-longer-used unsolicited
response payload.
b) In turn, this means that most NVIDIA codecs can simply use
patch_generic_hdmi instead of having a custom variant just to set
old_pin_detect.
c) When PD && ELDV becomes true, no extra verbs are executed, because the
GetPinSense that was previously executed by snd_hdmi_get_eld (really,
hdmi_eld_valid) has simply moved into hdmi_present_sense.
d) When PD && ELDV becomes false, there is a single extra GetPinSense verb
executed for codecs where old_pin_detect wasn't set, i.e. some NVIDIA,
and all ATI/AMD and Intel codecs. I doubt this will be a performance
issue.
The new unified code in hdmi_present_sense also ensures that eld->eld_valid
is not set unless eld->monitor_present is also set. This protects against
potential invalid combinations of PD and ELDV received from HW, and
transitively from a graphics driver.
Also, print the derived PD/ELDV bits from hdmi_present_sense so the kernel
log always displays the actual state stored, which will differ from the
values in the unsolicited response for NVIDIA HW where old_pin_detect was
previously set.
Finally, a couple of small tweaks originally by Takashi:
* Clear the ELD content to zero before reading it, so that if it's not
read (i.e. when !(PD && ELDV)) it's in a known state.
* Don't show ELD fields in /proc ELD files when the ELD isn't valid.
The only possibility I can see for regression here is a codec where the
GetPinSense verb returns incorrect data. However, we're already exposed
to that, since that data is used (a) from hdmi_add_pin to set up the
initial pin state, and (b) within snd_hda_input_jack_report to query
a pin's presence value. As such, I don't believe any HW has bugs here.
Includes-changes-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-05-25 07:11:17 +08:00
|
|
|
/*
|
|
|
|
* Always execute a GetPinSense verb here, even when called from
|
|
|
|
* hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
|
|
|
|
* response's PD bit is not the real PD value, but indicates that
|
|
|
|
* the real PD value changed. An older version of the HD-audio
|
|
|
|
* specification worked this way. Hence, we just ignore the data in
|
|
|
|
* the unsolicited response to avoid custom WARs.
|
|
|
|
*/
|
2010-03-08 10:44:23 +08:00
|
|
|
int present = snd_hda_pin_sense(codec, pin_nid);
|
2013-02-19 23:11:25 +08:00
|
|
|
bool update_eld = false;
|
|
|
|
bool eld_changed = false;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_lock(&per_pin->lock);
|
2013-02-19 23:11:25 +08:00
|
|
|
pin_eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
|
|
|
|
if (pin_eld->monitor_present)
|
|
|
|
eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
|
|
|
|
else
|
|
|
|
eld->eld_valid = false;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2012-04-10 17:00:35 +08:00
|
|
|
_snd_printd(SND_PR_VERBOSE,
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
|
2013-03-28 17:21:28 +08:00
|
|
|
codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid);
|
ALSA: HDA: Unify HDMI hotplug handling.
This change unifies the initial handling of a pin's state with the code to
update a pin's state after a hotplug (unsolicited response) event. The
initial probing, and all updates, are now routed through hdmi_present_sense.
The stored PD and ELDV status is now always derived from GetPinSense verb
execution, and not from the data in the unsolicited response. This means:
a) The WAR for NVIDIA codec's UR.PD values ("old_pin_detect") can be
removed, since this only affected the no-longer-used unsolicited
response payload.
b) In turn, this means that most NVIDIA codecs can simply use
patch_generic_hdmi instead of having a custom variant just to set
old_pin_detect.
c) When PD && ELDV becomes true, no extra verbs are executed, because the
GetPinSense that was previously executed by snd_hdmi_get_eld (really,
hdmi_eld_valid) has simply moved into hdmi_present_sense.
d) When PD && ELDV becomes false, there is a single extra GetPinSense verb
executed for codecs where old_pin_detect wasn't set, i.e. some NVIDIA,
and all ATI/AMD and Intel codecs. I doubt this will be a performance
issue.
The new unified code in hdmi_present_sense also ensures that eld->eld_valid
is not set unless eld->monitor_present is also set. This protects against
potential invalid combinations of PD and ELDV received from HW, and
transitively from a graphics driver.
Also, print the derived PD/ELDV bits from hdmi_present_sense so the kernel
log always displays the actual state stored, which will differ from the
values in the unsolicited response for NVIDIA HW where old_pin_detect was
previously set.
Finally, a couple of small tweaks originally by Takashi:
* Clear the ELD content to zero before reading it, so that if it's not
read (i.e. when !(PD && ELDV)) it's in a known state.
* Don't show ELD fields in /proc ELD files when the ELD isn't valid.
The only possibility I can see for regression here is a codec where the
GetPinSense verb returns incorrect data. However, we're already exposed
to that, since that data is used (a) from hdmi_add_pin to set up the
initial pin state, and (b) within snd_hda_input_jack_report to query
a pin's presence value. As such, I don't believe any HW has bugs here.
Includes-changes-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-05-25 07:11:17 +08:00
|
|
|
|
2013-02-19 23:11:25 +08:00
|
|
|
if (eld->eld_valid) {
|
2013-02-19 23:11:24 +08:00
|
|
|
if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
|
|
|
|
&eld->eld_size) < 0)
|
2013-02-19 23:11:25 +08:00
|
|
|
eld->eld_valid = false;
|
2013-02-19 23:11:24 +08:00
|
|
|
else {
|
|
|
|
memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
|
|
|
|
if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer,
|
|
|
|
eld->eld_size) < 0)
|
2013-02-19 23:11:25 +08:00
|
|
|
eld->eld_valid = false;
|
2013-02-19 23:11:24 +08:00
|
|
|
}
|
|
|
|
|
2013-02-19 23:11:25 +08:00
|
|
|
if (eld->eld_valid) {
|
2013-02-19 23:11:24 +08:00
|
|
|
snd_hdmi_show_eld(&eld->info);
|
2013-02-19 23:11:25 +08:00
|
|
|
update_eld = true;
|
2013-02-19 23:11:24 +08:00
|
|
|
}
|
2011-11-19 06:59:32 +08:00
|
|
|
else if (repoll) {
|
2011-11-16 16:29:47 +08:00
|
|
|
queue_delayed_work(codec->bus->workq,
|
|
|
|
&per_pin->work,
|
|
|
|
msecs_to_jiffies(300));
|
2013-10-18 00:03:24 +08:00
|
|
|
goto unlock;
|
2011-11-16 16:29:47 +08:00
|
|
|
}
|
|
|
|
}
|
2013-02-19 23:11:25 +08:00
|
|
|
|
2013-02-19 23:11:26 +08:00
|
|
|
if (pin_eld->eld_valid && !eld->eld_valid) {
|
2013-02-19 23:11:25 +08:00
|
|
|
update_eld = true;
|
2013-02-19 23:11:26 +08:00
|
|
|
eld_changed = true;
|
|
|
|
}
|
2013-02-19 23:11:25 +08:00
|
|
|
if (update_eld) {
|
2013-09-02 18:33:02 +08:00
|
|
|
bool old_eld_valid = pin_eld->eld_valid;
|
2013-02-19 23:11:25 +08:00
|
|
|
pin_eld->eld_valid = eld->eld_valid;
|
2013-02-19 23:11:26 +08:00
|
|
|
eld_changed = pin_eld->eld_size != eld->eld_size ||
|
|
|
|
memcmp(pin_eld->eld_buffer, eld->eld_buffer,
|
2013-02-19 23:11:25 +08:00
|
|
|
eld->eld_size) != 0;
|
|
|
|
if (eld_changed)
|
|
|
|
memcpy(pin_eld->eld_buffer, eld->eld_buffer,
|
|
|
|
eld->eld_size);
|
|
|
|
pin_eld->eld_size = eld->eld_size;
|
|
|
|
pin_eld->info = eld->info;
|
2013-09-02 18:33:02 +08:00
|
|
|
|
|
|
|
/* Haswell-specific workaround: re-setup when the transcoder is
|
|
|
|
* changed during the stream playback
|
|
|
|
*/
|
2013-09-05 04:36:57 +08:00
|
|
|
if (is_haswell(codec) &&
|
2013-09-05 04:37:12 +08:00
|
|
|
eld->eld_valid && !old_eld_valid && per_pin->setup)
|
2013-09-02 18:33:02 +08:00
|
|
|
hdmi_setup_audio_infoframe(codec, per_pin,
|
|
|
|
per_pin->non_pcm);
|
2013-02-19 23:11:25 +08:00
|
|
|
}
|
2013-02-19 23:11:26 +08:00
|
|
|
|
|
|
|
if (eld_changed)
|
|
|
|
snd_ctl_notify(codec->bus->card,
|
|
|
|
SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
|
|
|
|
&per_pin->eld_ctl->id);
|
2013-10-18 00:03:24 +08:00
|
|
|
unlock:
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
2011-11-16 16:29:47 +08:00
|
|
|
static void hdmi_repoll_eld(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct hdmi_spec_per_pin *per_pin =
|
|
|
|
container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work);
|
|
|
|
|
2011-11-19 06:59:32 +08:00
|
|
|
if (per_pin->repoll_count++ > 6)
|
|
|
|
per_pin->repoll_count = 0;
|
|
|
|
|
|
|
|
hdmi_present_sense(per_pin, per_pin->repoll_count);
|
2011-11-16 16:29:47 +08:00
|
|
|
}
|
|
|
|
|
2013-02-09 06:10:04 +08:00
|
|
|
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
|
|
|
|
hda_nid_t nid);
|
|
|
|
|
2010-03-08 10:44:23 +08:00
|
|
|
static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
unsigned int caps, config;
|
|
|
|
int pin_idx;
|
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
2011-05-19 17:46:03 +08:00
|
|
|
int err;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
2012-11-21 21:27:37 +08:00
|
|
|
caps = snd_hda_query_pin_caps(codec, pin_nid);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
|
|
|
|
return 0;
|
|
|
|
|
2012-11-21 21:27:37 +08:00
|
|
|
config = snd_hda_codec_get_pincfg(codec, pin_nid);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
if (get_defcfg_connect(config) == AC_JACK_PORT_NONE)
|
|
|
|
return 0;
|
|
|
|
|
2013-09-05 04:36:57 +08:00
|
|
|
if (is_haswell(codec))
|
2013-02-09 06:10:04 +08:00
|
|
|
intel_haswell_fixup_connect_list(codec, pin_nid);
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
pin_idx = spec->num_pins;
|
2013-03-13 21:40:31 +08:00
|
|
|
per_pin = snd_array_new(&spec->pins);
|
|
|
|
if (!per_pin)
|
|
|
|
return -ENOMEM;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
|
|
|
per_pin->pin_nid = pin_nid;
|
2012-09-06 23:42:08 +08:00
|
|
|
per_pin->non_pcm = false;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
err = hdmi_read_pin_conn(codec, pin_idx);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
|
|
|
spec->num_pins++;
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return 0;
|
2010-03-08 10:44:23 +08:00
|
|
|
}
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
2010-03-08 10:44:23 +08:00
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
|
|
|
unsigned int chans;
|
|
|
|
int err;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
chans = get_wcaps(codec, cvt_nid);
|
|
|
|
chans = get_wcaps_channels(chans);
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
per_cvt = snd_array_new(&spec->cvts);
|
|
|
|
if (!per_cvt)
|
|
|
|
return -ENOMEM;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
|
|
|
per_cvt->cvt_nid = cvt_nid;
|
|
|
|
per_cvt->channels_min = 2;
|
2012-07-31 17:36:00 +08:00
|
|
|
if (chans <= 16) {
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
per_cvt->channels_max = chans;
|
2012-07-31 17:36:00 +08:00
|
|
|
if (chans > spec->channels_max)
|
|
|
|
spec->channels_max = chans;
|
|
|
|
}
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
|
|
|
err = snd_hda_query_supported_pcm(codec, cvt_nid,
|
|
|
|
&per_cvt->rates,
|
|
|
|
&per_cvt->formats,
|
|
|
|
&per_cvt->maxbps);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids))
|
|
|
|
spec->cvt_nids[spec->num_cvts] = cvt_nid;
|
|
|
|
spec->num_cvts++;
|
2010-03-08 10:44:23 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hdmi_parse_codec(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
hda_nid_t nid;
|
|
|
|
int i, nodes;
|
|
|
|
|
|
|
|
nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
|
|
|
|
if (!nid || nodes < 0) {
|
|
|
|
snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nodes; i++, nid++) {
|
|
|
|
unsigned int caps;
|
|
|
|
unsigned int type;
|
|
|
|
|
2012-11-21 21:27:37 +08:00
|
|
|
caps = get_wcaps(codec, nid);
|
2010-03-08 10:44:23 +08:00
|
|
|
type = get_wcaps_type(caps);
|
|
|
|
|
|
|
|
if (!(caps & AC_WCAP_DIGITAL))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case AC_WID_AUD_OUT:
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hdmi_add_cvt(codec, nid);
|
2010-03-08 10:44:23 +08:00
|
|
|
break;
|
|
|
|
case AC_WID_PIN:
|
2010-05-14 16:36:15 +08:00
|
|
|
hdmi_add_pin(codec, nid);
|
2010-03-08 10:44:23 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-07 16:22:33 +08:00
|
|
|
#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;
|
2010-03-08 10:44:23 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2012-11-07 16:22:33 +08:00
|
|
|
else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
|
2010-03-08 10:44:23 +08:00
|
|
|
AC_PWRST_EPSS))
|
|
|
|
codec->bus->power_keep_link_on = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
/*
|
|
|
|
*/
|
2012-09-06 23:42:08 +08:00
|
|
|
static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid)
|
|
|
|
{
|
|
|
|
struct hda_spdif_out *spdif;
|
|
|
|
bool non_pcm;
|
|
|
|
|
|
|
|
mutex_lock(&codec->spdif_mutex);
|
|
|
|
spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid);
|
|
|
|
non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO);
|
|
|
|
mutex_unlock(&codec->spdif_mutex);
|
|
|
|
return non_pcm;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
/*
|
|
|
|
* HDMI callbacks
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
unsigned int stream_tag,
|
|
|
|
unsigned int format,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
hda_nid_t cvt_nid = hinfo->nid;
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int pin_idx = hinfo_to_pin_index(spec, hinfo);
|
2013-09-02 18:33:02 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
|
|
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
2012-09-06 23:42:08 +08:00
|
|
|
bool non_pcm;
|
|
|
|
|
|
|
|
non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_lock(&per_pin->lock);
|
2013-09-02 18:33:02 +08:00
|
|
|
per_pin->channels = substream->runtime->channels;
|
|
|
|
per_pin->setup = true;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
2013-09-02 18:33:02 +08:00
|
|
|
hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
|
2010-09-07 18:27:25 +08:00
|
|
|
}
|
|
|
|
|
2012-08-06 20:49:36 +08:00
|
|
|
static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
|
|
|
snd_hda_codec_cleanup_stream(codec, hinfo->nid);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-07-27 00:08:14 +08:00
|
|
|
static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream)
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int cvt_idx, pin_idx;
|
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
|
|
|
|
|
|
|
if (hinfo->nid) {
|
|
|
|
cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid);
|
|
|
|
if (snd_BUG_ON(cvt_idx < 0))
|
|
|
|
return -EINVAL;
|
2013-03-13 21:40:31 +08:00
|
|
|
per_cvt = get_cvt(spec, cvt_idx);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
|
|
|
snd_BUG_ON(!per_cvt->assigned);
|
|
|
|
per_cvt->assigned = 0;
|
|
|
|
hinfo->nid = 0;
|
|
|
|
|
|
|
|
pin_idx = hinfo_to_pin_index(spec, hinfo);
|
|
|
|
if (snd_BUG_ON(pin_idx < 0))
|
|
|
|
return -EINVAL;
|
2013-03-13 21:40:31 +08:00
|
|
|
per_pin = get_pin(spec, pin_idx);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
|
|
|
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
2013-10-18 00:03:24 +08:00
|
|
|
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_lock(&per_pin->lock);
|
2012-07-31 17:36:00 +08:00
|
|
|
per_pin->chmap_set = false;
|
|
|
|
memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
|
2013-09-02 18:33:02 +08:00
|
|
|
|
|
|
|
per_pin->setup = false;
|
|
|
|
per_pin->channels = 0;
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
}
|
2012-07-31 17:36:00 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct hda_pcm_ops generic_ops = {
|
|
|
|
.open = hdmi_pcm_open,
|
2012-07-27 00:08:14 +08:00
|
|
|
.close = hdmi_pcm_close,
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
.prepare = generic_hdmi_playback_pcm_prepare,
|
2012-08-06 20:49:36 +08:00
|
|
|
.cleanup = generic_hdmi_playback_pcm_cleanup,
|
2010-09-07 18:27:25 +08:00
|
|
|
};
|
|
|
|
|
2012-07-31 17:36:00 +08:00
|
|
|
/*
|
|
|
|
* ALSA API channel-map control callbacks
|
|
|
|
*/
|
|
|
|
static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol,
|
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
|
{
|
|
|
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
|
|
|
struct hda_codec *codec = info->private_data;
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
|
|
|
uinfo->count = spec->channels_max;
|
|
|
|
uinfo->value.integer.min = 0;
|
|
|
|
uinfo->value.integer.max = SNDRV_CHMAP_LAST;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
|
|
unsigned int size, unsigned int __user *tlv)
|
|
|
|
{
|
|
|
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
|
|
|
struct hda_codec *codec = info->private_data;
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
unsigned int __user *dst;
|
|
|
|
int chs, count = 0;
|
|
|
|
|
|
|
|
if (size < 8)
|
|
|
|
return -ENOMEM;
|
|
|
|
if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv))
|
|
|
|
return -EFAULT;
|
|
|
|
size -= 8;
|
|
|
|
dst = tlv + 2;
|
2012-09-10 22:08:40 +08:00
|
|
|
for (chs = 2; chs <= spec->channels_max; chs++) {
|
2012-07-31 17:36:00 +08:00
|
|
|
int i, c;
|
|
|
|
struct cea_channel_speaker_allocation *cap;
|
|
|
|
cap = channel_allocations;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) {
|
|
|
|
int chs_bytes = chs * 4;
|
|
|
|
if (cap->channels != chs)
|
|
|
|
continue;
|
|
|
|
if (size < 8)
|
|
|
|
return -ENOMEM;
|
|
|
|
if (put_user(SNDRV_CTL_TLVT_CHMAP_VAR, dst) ||
|
|
|
|
put_user(chs_bytes, dst + 1))
|
|
|
|
return -EFAULT;
|
|
|
|
dst += 2;
|
|
|
|
size -= 8;
|
|
|
|
count += 8;
|
|
|
|
if (size < chs_bytes)
|
|
|
|
return -ENOMEM;
|
|
|
|
size -= chs_bytes;
|
|
|
|
count += chs_bytes;
|
|
|
|
for (c = 7; c >= 0; c--) {
|
|
|
|
int spk = cap->speakers[c];
|
|
|
|
if (!spk)
|
|
|
|
continue;
|
|
|
|
if (put_user(spk_to_chmap(spk), dst))
|
|
|
|
return -EFAULT;
|
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (put_user(count, tlv + 1))
|
|
|
|
return -EFAULT;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol,
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
{
|
|
|
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
|
|
|
struct hda_codec *codec = info->private_data;
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int pin_idx = kcontrol->private_value;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
2012-07-31 17:36:00 +08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++)
|
|
|
|
ucontrol->value.integer.value[i] = per_pin->chmap[i];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
|
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
|
{
|
|
|
|
struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
|
|
|
|
struct hda_codec *codec = info->private_data;
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int pin_idx = kcontrol->private_value;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
2012-07-31 17:36:00 +08:00
|
|
|
unsigned int ctl_idx;
|
|
|
|
struct snd_pcm_substream *substream;
|
|
|
|
unsigned char chmap[8];
|
|
|
|
int i, ca, prepared = 0;
|
|
|
|
|
|
|
|
ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
|
|
|
|
substream = snd_pcm_chmap_substream(info, ctl_idx);
|
|
|
|
if (!substream || !substream->runtime)
|
2013-01-15 21:44:41 +08:00
|
|
|
return 0; /* just for avoiding error from alsactl restore */
|
2012-07-31 17:36:00 +08:00
|
|
|
switch (substream->runtime->status->state) {
|
|
|
|
case SNDRV_PCM_STATE_OPEN:
|
|
|
|
case SNDRV_PCM_STATE_SETUP:
|
|
|
|
break;
|
|
|
|
case SNDRV_PCM_STATE_PREPARED:
|
|
|
|
prepared = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EBUSY;
|
|
|
|
}
|
|
|
|
memset(chmap, 0, sizeof(chmap));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(chmap); i++)
|
|
|
|
chmap[i] = ucontrol->value.integer.value[i];
|
|
|
|
if (!memcmp(chmap, per_pin->chmap, sizeof(chmap)))
|
|
|
|
return 0;
|
|
|
|
ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap);
|
|
|
|
if (ca < 0)
|
|
|
|
return -EINVAL;
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_lock(&per_pin->lock);
|
2012-07-31 17:36:00 +08:00
|
|
|
per_pin->chmap_set = true;
|
|
|
|
memcpy(per_pin->chmap, chmap, sizeof(chmap));
|
|
|
|
if (prepared)
|
2013-09-02 18:33:02 +08:00
|
|
|
hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_unlock(&per_pin->lock);
|
2012-07-31 17:36:00 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static int generic_hdmi_build_pcms(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int pin_idx;
|
2010-09-07 18:27:25 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
|
|
|
struct hda_pcm *info;
|
2010-09-07 18:27:25 +08:00
|
|
|
struct hda_pcm_stream *pstr;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
|
|
|
|
|
|
|
per_pin = get_pin(spec, pin_idx);
|
|
|
|
sprintf(per_pin->pcm_name, "HDMI %d", pin_idx);
|
|
|
|
info = snd_array_new(&spec->pcm_rec);
|
|
|
|
if (!info)
|
|
|
|
return -ENOMEM;
|
|
|
|
info->name = per_pin->pcm_name;
|
2010-09-07 18:27:25 +08:00
|
|
|
info->pcm_type = HDA_PCM_TYPE_HDMI;
|
2012-07-31 17:36:00 +08:00
|
|
|
info->own_chmap = true;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
pstr->substreams = 1;
|
|
|
|
pstr->ops = generic_ops;
|
|
|
|
/* other pstr fields are set in open */
|
2010-09-07 18:27:25 +08:00
|
|
|
}
|
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
codec->num_pcms = spec->num_pins;
|
2013-03-13 21:40:31 +08:00
|
|
|
codec->pcm_info = spec->pcm_rec.list;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-23 22:56:03 +08:00
|
|
|
static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
|
|
|
|
{
|
2011-12-02 00:41:36 +08:00
|
|
|
char hdmi_str[32] = "HDMI/DP";
|
2011-08-23 22:56:03 +08:00
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
|
|
|
int pcmdev = get_pcm_rec(spec, pin_idx)->device;
|
2011-08-23 22:56:03 +08:00
|
|
|
|
2011-12-02 00:41:36 +08:00
|
|
|
if (pcmdev > 0)
|
|
|
|
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
|
2013-02-22 17:16:28 +08:00
|
|
|
if (!is_jack_detectable(codec, per_pin->pin_nid))
|
|
|
|
strncat(hdmi_str, " Phantom",
|
|
|
|
sizeof(hdmi_str) - strlen(hdmi_str) - 1);
|
2011-08-23 22:56:03 +08:00
|
|
|
|
2011-12-02 00:41:36 +08:00
|
|
|
return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0);
|
2011-08-23 22:56:03 +08:00
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static int generic_hdmi_build_controls(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int err;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int pin_idx;
|
2010-09-07 18:27:25 +08:00
|
|
|
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
2011-08-23 22:56:03 +08:00
|
|
|
|
|
|
|
err = generic_hdmi_build_jack(codec, pin_idx);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2012-10-12 23:24:51 +08:00
|
|
|
err = snd_hda_create_dig_out_ctls(codec,
|
|
|
|
per_pin->pin_nid,
|
|
|
|
per_pin->mux_nids[0],
|
|
|
|
HDA_PCM_TYPE_HDMI);
|
2010-09-07 18:27:25 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
snd_hda_spdif_ctls_unassign(codec, pin_idx);
|
2011-10-01 05:35:41 +08:00
|
|
|
|
|
|
|
/* add control for ELD Bytes */
|
2013-03-13 21:40:31 +08:00
|
|
|
err = hdmi_create_eld_ctl(codec, pin_idx,
|
|
|
|
get_pcm_rec(spec, pin_idx)->device);
|
2011-10-01 05:35:41 +08:00
|
|
|
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2011-12-02 00:41:36 +08:00
|
|
|
|
2011-12-20 22:53:07 +08:00
|
|
|
hdmi_present_sense(per_pin, 0);
|
2010-09-07 18:27:25 +08:00
|
|
|
}
|
|
|
|
|
2012-07-31 17:36:00 +08:00
|
|
|
/* add channel maps */
|
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
|
|
|
struct snd_pcm_chmap *chmap;
|
|
|
|
struct snd_kcontrol *kctl;
|
|
|
|
int i;
|
2013-08-22 15:55:36 +08:00
|
|
|
|
|
|
|
if (!codec->pcm_info[pin_idx].pcm)
|
|
|
|
break;
|
2012-07-31 17:36:00 +08:00
|
|
|
err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm,
|
|
|
|
SNDRV_PCM_STREAM_PLAYBACK,
|
|
|
|
NULL, 0, pin_idx, &chmap);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
/* override handlers */
|
|
|
|
chmap->private_data = codec;
|
|
|
|
kctl = chmap->kctl;
|
|
|
|
for (i = 0; i < kctl->count; i++)
|
|
|
|
kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
|
|
|
|
kctl->info = hdmi_chmap_ctl_info;
|
|
|
|
kctl->get = hdmi_chmap_ctl_get;
|
|
|
|
kctl->put = hdmi_chmap_ctl_put;
|
|
|
|
kctl->tlv.c = hdmi_chmap_ctl_tlv;
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-06-20 22:32:22 +08:00
|
|
|
static int generic_hdmi_init_per_pins(struct hda_codec *codec)
|
2010-09-07 18:27:25 +08:00
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
2011-11-16 16:29:47 +08:00
|
|
|
per_pin->codec = codec;
|
2013-10-18 00:21:12 +08:00
|
|
|
mutex_init(&per_pin->lock);
|
2011-11-16 16:29:47 +08:00
|
|
|
INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
|
2013-10-18 00:21:12 +08:00
|
|
|
eld_proc_new(per_pin, pin_idx);
|
2010-09-07 18:27:25 +08:00
|
|
|
}
|
2012-06-20 22:32:22 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int generic_hdmi_init(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
2012-06-20 22:32:22 +08:00
|
|
|
hda_nid_t pin_nid = per_pin->pin_nid;
|
|
|
|
|
|
|
|
hdmi_init_pin(codec, pin_nid);
|
|
|
|
snd_hda_jack_detect_enable(codec, pin_nid, pin_nid);
|
|
|
|
}
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
static void hdmi_array_init(struct hdmi_spec *spec, int nums)
|
|
|
|
{
|
|
|
|
snd_array_init(&spec->pins, sizeof(struct hdmi_spec_per_pin), nums);
|
|
|
|
snd_array_init(&spec->cvts, sizeof(struct hdmi_spec_per_cvt), nums);
|
|
|
|
snd_array_init(&spec->pcm_rec, sizeof(struct hda_pcm), nums);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hdmi_array_free(struct hdmi_spec *spec)
|
|
|
|
{
|
|
|
|
snd_array_free(&spec->pins);
|
|
|
|
snd_array_free(&spec->cvts);
|
|
|
|
snd_array_free(&spec->pcm_rec);
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static void generic_hdmi_free(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
2011-11-16 16:29:47 +08:00
|
|
|
cancel_delayed_work(&per_pin->work);
|
2013-10-18 00:21:12 +08:00
|
|
|
eld_proc_free(per_pin);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
}
|
2010-09-07 18:27:25 +08:00
|
|
|
|
2011-11-16 16:29:47 +08:00
|
|
|
flush_workqueue(codec->bus->workq);
|
2013-03-13 21:40:31 +08:00
|
|
|
hdmi_array_free(spec);
|
2010-09-07 18:27:25 +08:00
|
|
|
kfree(spec);
|
|
|
|
}
|
|
|
|
|
2013-06-24 19:45:23 +08:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
static int generic_hdmi_resume(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int pin_idx;
|
|
|
|
|
|
|
|
generic_hdmi_init(codec);
|
|
|
|
snd_hda_codec_resume_amp(codec);
|
|
|
|
snd_hda_codec_resume_cache(codec);
|
|
|
|
|
|
|
|
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
|
|
|
|
hdmi_present_sense(per_pin, 1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-05-02 18:17:41 +08:00
|
|
|
static const struct hda_codec_ops generic_hdmi_patch_ops = {
|
2010-09-07 18:27:25 +08:00
|
|
|
.init = generic_hdmi_init,
|
|
|
|
.free = generic_hdmi_free,
|
|
|
|
.build_pcms = generic_hdmi_build_pcms,
|
|
|
|
.build_controls = generic_hdmi_build_controls,
|
|
|
|
.unsol_event = hdmi_unsol_event,
|
2013-06-24 19:45:23 +08:00
|
|
|
#ifdef CONFIG_PM
|
|
|
|
.resume = generic_hdmi_resume,
|
|
|
|
#endif
|
2010-09-07 18:27:25 +08:00
|
|
|
};
|
|
|
|
|
2012-12-19 05:59:15 +08:00
|
|
|
|
2013-02-09 06:10:04 +08:00
|
|
|
static void intel_haswell_fixup_connect_list(struct hda_codec *codec,
|
|
|
|
hda_nid_t nid)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
hda_nid_t conns[4];
|
|
|
|
int nconns;
|
2012-12-19 05:59:15 +08:00
|
|
|
|
2013-02-09 06:10:04 +08:00
|
|
|
nconns = snd_hda_get_connections(codec, nid, conns, ARRAY_SIZE(conns));
|
|
|
|
if (nconns == spec->num_cvts &&
|
|
|
|
!memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t)))
|
2012-12-19 05:59:15 +08:00
|
|
|
return;
|
|
|
|
|
2013-02-09 06:10:04 +08:00
|
|
|
/* override pins connection list */
|
|
|
|
snd_printdd("hdmi: haswell: override pin connection 0x%x\n", nid);
|
|
|
|
snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids);
|
2012-12-19 05:59:15 +08:00
|
|
|
}
|
|
|
|
|
2013-02-09 06:09:52 +08:00
|
|
|
#define INTEL_VENDOR_NID 0x08
|
|
|
|
#define INTEL_GET_VENDOR_VERB 0xf81
|
|
|
|
#define INTEL_SET_VENDOR_VERB 0x781
|
|
|
|
#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */
|
|
|
|
#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */
|
|
|
|
|
|
|
|
static void intel_haswell_enable_all_pins(struct hda_codec *codec,
|
2013-05-08 14:09:34 +08:00
|
|
|
bool update_tree)
|
2013-02-09 06:09:52 +08:00
|
|
|
{
|
|
|
|
unsigned int vendor_param;
|
|
|
|
|
|
|
|
vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0,
|
|
|
|
INTEL_GET_VENDOR_VERB, 0);
|
|
|
|
if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS)
|
|
|
|
return;
|
|
|
|
|
|
|
|
vendor_param |= INTEL_EN_ALL_PIN_CVTS;
|
|
|
|
vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0,
|
|
|
|
INTEL_SET_VENDOR_VERB, vendor_param);
|
|
|
|
if (vendor_param == -1)
|
|
|
|
return;
|
|
|
|
|
2013-05-08 14:09:34 +08:00
|
|
|
if (update_tree)
|
|
|
|
snd_hda_codec_update_widgets(codec);
|
2013-02-09 06:09:52 +08:00
|
|
|
}
|
|
|
|
|
2013-02-09 06:10:04 +08:00
|
|
|
static void intel_haswell_fixup_enable_dp12(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
unsigned int vendor_param;
|
|
|
|
|
|
|
|
vendor_param = snd_hda_codec_read(codec, INTEL_VENDOR_NID, 0,
|
|
|
|
INTEL_GET_VENDOR_VERB, 0);
|
|
|
|
if (vendor_param == -1 || vendor_param & INTEL_EN_DP12)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* enable DP1.2 mode */
|
|
|
|
vendor_param |= INTEL_EN_DP12;
|
|
|
|
snd_hda_codec_write_cache(codec, INTEL_VENDOR_NID, 0,
|
|
|
|
INTEL_SET_VENDOR_VERB, vendor_param);
|
|
|
|
}
|
|
|
|
|
2013-05-08 14:09:34 +08:00
|
|
|
/* Haswell needs to re-issue the vendor-specific verbs before turning to D0.
|
|
|
|
* Otherwise you may get severe h/w communication errors.
|
|
|
|
*/
|
|
|
|
static void haswell_set_power_state(struct hda_codec *codec, hda_nid_t fg,
|
|
|
|
unsigned int power_state)
|
|
|
|
{
|
|
|
|
if (power_state == AC_PWRST_D0) {
|
|
|
|
intel_haswell_enable_all_pins(codec, false);
|
|
|
|
intel_haswell_fixup_enable_dp12(codec);
|
|
|
|
}
|
2013-02-09 06:10:04 +08:00
|
|
|
|
2013-05-08 14:09:34 +08:00
|
|
|
snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, power_state);
|
|
|
|
snd_hda_codec_set_power_to_all(codec, fg, power_state);
|
|
|
|
}
|
2012-12-19 05:59:15 +08:00
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static int patch_generic_hdmi(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec;
|
|
|
|
|
|
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
|
|
if (spec == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
codec->spec = spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
hdmi_array_init(spec, 4);
|
2012-12-19 05:59:15 +08:00
|
|
|
|
2013-09-05 04:36:57 +08:00
|
|
|
if (is_haswell(codec)) {
|
2013-05-08 14:09:34 +08:00
|
|
|
intel_haswell_enable_all_pins(codec, true);
|
2013-02-09 06:10:04 +08:00
|
|
|
intel_haswell_fixup_enable_dp12(codec);
|
2013-05-08 14:09:34 +08:00
|
|
|
}
|
2012-12-19 05:59:15 +08:00
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
if (hdmi_parse_codec(codec) < 0) {
|
|
|
|
codec->spec = NULL;
|
|
|
|
kfree(spec);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
codec->patch_ops = generic_hdmi_patch_ops;
|
2013-09-05 04:36:57 +08:00
|
|
|
if (is_haswell(codec)) {
|
2013-05-08 14:09:34 +08:00
|
|
|
codec->patch_ops.set_power_state = haswell_set_power_state;
|
2013-08-27 09:35:41 +08:00
|
|
|
codec->dp_mst = true;
|
|
|
|
}
|
2013-05-08 14:09:34 +08:00
|
|
|
|
2012-06-20 22:32:22 +08:00
|
|
|
generic_hdmi_init_per_pins(codec);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
|
|
|
init_channel_allocations();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-06-02 01:14:19 +08:00
|
|
|
/*
|
|
|
|
* Shared non-generic implementations
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int simple_playback_build_pcms(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hda_pcm *info;
|
2012-06-21 14:23:27 +08:00
|
|
|
unsigned int chans;
|
|
|
|
struct hda_pcm_stream *pstr;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
2011-06-02 01:14:19 +08:00
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
per_cvt = get_cvt(spec, 0);
|
|
|
|
chans = get_wcaps(codec, per_cvt->cvt_nid);
|
2012-06-21 14:23:27 +08:00
|
|
|
chans = get_wcaps_channels(chans);
|
2011-06-02 01:14:19 +08:00
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
info = snd_array_new(&spec->pcm_rec);
|
|
|
|
if (!info)
|
|
|
|
return -ENOMEM;
|
|
|
|
info->name = get_pin(spec, 0)->pcm_name;
|
|
|
|
sprintf(info->name, "HDMI 0");
|
2012-06-21 14:23:27 +08:00
|
|
|
info->pcm_type = HDA_PCM_TYPE_HDMI;
|
|
|
|
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
|
|
|
|
*pstr = spec->pcm_playback;
|
2013-03-13 21:40:31 +08:00
|
|
|
pstr->nid = per_cvt->cvt_nid;
|
2012-06-21 14:23:27 +08:00
|
|
|
if (pstr->channels_max <= 2 && chans && chans <= 16)
|
|
|
|
pstr->channels_max = chans;
|
2011-06-02 01:14:19 +08:00
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
codec->num_pcms = 1;
|
|
|
|
codec->pcm_info = info;
|
|
|
|
|
2011-06-02 01:14:19 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-06-15 17:53:32 +08:00
|
|
|
/* unsolicited event for jack sensing */
|
|
|
|
static void simple_hdmi_unsol_event(struct hda_codec *codec,
|
|
|
|
unsigned int res)
|
|
|
|
{
|
2012-06-21 16:43:15 +08:00
|
|
|
snd_hda_jack_set_dirty_all(codec);
|
2012-06-15 17:53:32 +08:00
|
|
|
snd_hda_jack_report_sync(codec);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* generic_hdmi_build_jack can be used for simple_hdmi, too,
|
|
|
|
* as long as spec->pins[] is set correctly
|
|
|
|
*/
|
|
|
|
#define simple_hdmi_build_jack generic_hdmi_build_jack
|
|
|
|
|
2011-06-02 01:14:19 +08:00
|
|
|
static int simple_playback_build_controls(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
2011-06-02 01:14:19 +08:00
|
|
|
int err;
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
per_cvt = get_cvt(spec, 0);
|
|
|
|
err = snd_hda_create_spdif_out_ctls(codec, per_cvt->cvt_nid,
|
|
|
|
per_cvt->cvt_nid);
|
2012-06-21 14:23:27 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
return simple_hdmi_build_jack(codec, 0);
|
2011-06-02 01:14:19 +08:00
|
|
|
}
|
|
|
|
|
2012-06-15 18:45:43 +08:00
|
|
|
static int simple_playback_init(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_pin *per_pin = get_pin(spec, 0);
|
|
|
|
hda_nid_t pin = per_pin->pin_nid;
|
2012-06-21 14:23:27 +08:00
|
|
|
|
|
|
|
snd_hda_codec_write(codec, pin, 0,
|
|
|
|
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
|
|
|
|
/* some codecs require to unmute the pin */
|
|
|
|
if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
|
|
|
|
snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE,
|
|
|
|
AMP_OUT_UNMUTE);
|
|
|
|
snd_hda_jack_detect_enable(codec, pin, pin);
|
2012-06-15 18:45:43 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-06-02 01:14:19 +08:00
|
|
|
static void simple_playback_free(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
|
2013-03-13 21:40:31 +08:00
|
|
|
hdmi_array_free(spec);
|
2011-06-02 01:14:19 +08:00
|
|
|
kfree(spec);
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
/*
|
|
|
|
* Nvidia specific implementations
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define Nv_VERB_SET_Channel_Allocation 0xF79
|
|
|
|
#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
|
|
|
|
#define Nv_VERB_SET_Audio_Protection_On 0xF98
|
|
|
|
#define Nv_VERB_SET_Audio_Protection_Off 0xF99
|
|
|
|
|
|
|
|
#define nvhdmi_master_con_nid_7x 0x04
|
|
|
|
#define nvhdmi_master_pin_nid_7x 0x05
|
|
|
|
|
2011-05-02 18:17:41 +08:00
|
|
|
static const hda_nid_t nvhdmi_con_nids_7x[4] = {
|
2010-09-07 18:27:25 +08:00
|
|
|
/*front, rear, clfe, rear_surr */
|
|
|
|
0x6, 0x8, 0xa, 0xc,
|
|
|
|
};
|
|
|
|
|
2012-06-15 20:38:31 +08:00
|
|
|
static const struct hda_verb nvhdmi_basic_init_7x_2ch[] = {
|
|
|
|
/* set audio protect on */
|
|
|
|
{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
|
|
|
|
/* enable digital output on pin widget */
|
|
|
|
{ 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
|
|
|
|
{} /* terminator */
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct hda_verb nvhdmi_basic_init_7x_8ch[] = {
|
2010-09-07 18:27:25 +08:00
|
|
|
/* set audio protect on */
|
|
|
|
{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
|
|
|
|
/* enable digital output on pin widget */
|
|
|
|
{ 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
|
|
|
|
{ 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
|
|
|
|
{ 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
|
|
|
|
{ 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
|
|
|
|
{ 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
|
|
|
|
{} /* terminator */
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef LIMITED_RATE_FMT_SUPPORT
|
|
|
|
/* support only the safe format and rate */
|
|
|
|
#define SUPPORTED_RATES SNDRV_PCM_RATE_48000
|
|
|
|
#define SUPPORTED_MAXBPS 16
|
|
|
|
#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE
|
|
|
|
#else
|
|
|
|
/* support all rates and formats */
|
|
|
|
#define SUPPORTED_RATES \
|
|
|
|
(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
|
|
|
|
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
|
|
|
|
SNDRV_PCM_RATE_192000)
|
|
|
|
#define SUPPORTED_MAXBPS 24
|
|
|
|
#define SUPPORTED_FORMATS \
|
|
|
|
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
|
|
|
|
#endif
|
|
|
|
|
2012-06-15 20:38:31 +08:00
|
|
|
static int nvhdmi_7x_init_2ch(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_2ch);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int nvhdmi_7x_init_8ch(struct hda_codec *codec)
|
2010-09-07 18:27:25 +08:00
|
|
|
{
|
2012-06-15 20:38:31 +08:00
|
|
|
snd_hda_sequence_write(codec, nvhdmi_basic_init_7x_8ch);
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-11 00:19:31 +08:00
|
|
|
static unsigned int channels_2_6_8[] = {
|
|
|
|
2, 6, 8
|
|
|
|
};
|
|
|
|
|
|
|
|
static unsigned int channels_2_8[] = {
|
|
|
|
2, 8
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = {
|
|
|
|
.count = ARRAY_SIZE(channels_2_6_8),
|
|
|
|
.list = channels_2_6_8,
|
|
|
|
.mask = 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = {
|
|
|
|
.count = ARRAY_SIZE(channels_2_8),
|
|
|
|
.list = channels_2_8,
|
|
|
|
.mask = 0,
|
|
|
|
};
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2011-01-11 00:19:31 +08:00
|
|
|
struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL;
|
|
|
|
|
|
|
|
switch (codec->preset->id) {
|
|
|
|
case 0x10de0002:
|
|
|
|
case 0x10de0003:
|
|
|
|
case 0x10de0005:
|
|
|
|
case 0x10de0006:
|
|
|
|
hw_constraints_channels = &hw_constraints_2_8_channels;
|
|
|
|
break;
|
|
|
|
case 0x10de0007:
|
|
|
|
hw_constraints_channels = &hw_constraints_2_6_8_channels;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hw_constraints_channels != NULL) {
|
|
|
|
snd_pcm_hw_constraint_list(substream->runtime, 0,
|
|
|
|
SNDRV_PCM_HW_PARAM_CHANNELS,
|
|
|
|
hw_constraints_channels);
|
2011-01-14 16:42:27 +08:00
|
|
|
} else {
|
|
|
|
snd_pcm_hw_constraint_step(substream->runtime, 0,
|
|
|
|
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
|
2011-01-11 00:19:31 +08:00
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int simple_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 hdmi_spec *spec = codec->spec;
|
|
|
|
return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
|
|
|
|
stream_tag, format, substream);
|
|
|
|
}
|
|
|
|
|
2012-06-15 20:34:42 +08:00
|
|
|
static const struct hda_pcm_stream simple_pcm_playback = {
|
|
|
|
.substreams = 1,
|
|
|
|
.channels_min = 2,
|
|
|
|
.channels_max = 2,
|
|
|
|
.ops = {
|
|
|
|
.open = simple_playback_pcm_open,
|
|
|
|
.close = simple_playback_pcm_close,
|
|
|
|
.prepare = simple_playback_pcm_prepare
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct hda_codec_ops simple_hdmi_patch_ops = {
|
|
|
|
.build_controls = simple_playback_build_controls,
|
|
|
|
.build_pcms = simple_playback_build_pcms,
|
|
|
|
.init = simple_playback_init,
|
|
|
|
.free = simple_playback_free,
|
2012-06-15 20:40:21 +08:00
|
|
|
.unsol_event = simple_hdmi_unsol_event,
|
2012-06-15 20:34:42 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static int patch_simple_hdmi(struct hda_codec *codec,
|
|
|
|
hda_nid_t cvt_nid, hda_nid_t pin_nid)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
|
|
|
struct hdmi_spec_per_pin *per_pin;
|
2012-06-15 20:34:42 +08:00
|
|
|
|
|
|
|
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
|
|
|
if (!spec)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
codec->spec = spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
hdmi_array_init(spec, 1);
|
2012-06-15 20:34:42 +08:00
|
|
|
|
|
|
|
spec->multiout.num_dacs = 0; /* no analog */
|
|
|
|
spec->multiout.max_channels = 2;
|
|
|
|
spec->multiout.dig_out_nid = cvt_nid;
|
|
|
|
spec->num_cvts = 1;
|
|
|
|
spec->num_pins = 1;
|
2013-03-13 21:40:31 +08:00
|
|
|
per_pin = snd_array_new(&spec->pins);
|
|
|
|
per_cvt = snd_array_new(&spec->cvts);
|
|
|
|
if (!per_pin || !per_cvt) {
|
|
|
|
simple_playback_free(codec);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
per_cvt->cvt_nid = cvt_nid;
|
|
|
|
per_pin->pin_nid = pin_nid;
|
2012-06-15 20:34:42 +08:00
|
|
|
spec->pcm_playback = simple_pcm_playback;
|
|
|
|
|
|
|
|
codec->patch_ops = simple_hdmi_patch_ops;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-07 08:19:04 +08:00
|
|
|
static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
|
|
|
|
int channels)
|
|
|
|
{
|
|
|
|
unsigned int chanmask;
|
|
|
|
int chan = channels ? (channels - 1) : 1;
|
|
|
|
|
|
|
|
switch (channels) {
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
case 2:
|
|
|
|
chanmask = 0x00;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
chanmask = 0x08;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
chanmask = 0x0b;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
chanmask = 0x13;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the audio infoframe channel allocation and checksum fields. The
|
|
|
|
* channel count is computed implicitly by the hardware. */
|
|
|
|
snd_hda_codec_write(codec, 0x1, 0,
|
|
|
|
Nv_VERB_SET_Channel_Allocation, chanmask);
|
|
|
|
|
|
|
|
snd_hda_codec_write(codec, 0x1, 0,
|
|
|
|
Nv_VERB_SET_Info_Frame_Checksum,
|
|
|
|
(0x71 - chan - chanmask));
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
|
|
|
|
0, AC_VERB_SET_CHANNEL_STREAMID, 0);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
/* set the stream id */
|
|
|
|
snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
|
|
|
|
AC_VERB_SET_CHANNEL_STREAMID, 0);
|
|
|
|
/* set the stream format */
|
|
|
|
snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
|
|
|
|
AC_VERB_SET_STREAM_FORMAT, 0);
|
|
|
|
}
|
|
|
|
|
2011-04-07 08:19:04 +08:00
|
|
|
/* The audio hardware sends a channel count of 0x7 (8ch) when all the
|
|
|
|
* streams are disabled. */
|
|
|
|
nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
unsigned int stream_tag,
|
|
|
|
unsigned int format,
|
|
|
|
struct snd_pcm_substream *substream)
|
|
|
|
{
|
|
|
|
int chs;
|
2011-11-03 04:40:06 +08:00
|
|
|
unsigned int dataDCC2, channel_id;
|
2010-09-07 18:27:25 +08:00
|
|
|
int i;
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2012-05-10 16:21:29 +08:00
|
|
|
struct hda_spdif_out *spdif;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_cvt *per_cvt;
|
2010-09-07 18:27:25 +08:00
|
|
|
|
|
|
|
mutex_lock(&codec->spdif_mutex);
|
2013-03-13 21:40:31 +08:00
|
|
|
per_cvt = get_cvt(spec, 0);
|
|
|
|
spdif = snd_hda_spdif_out_of_nid(codec, per_cvt->cvt_nid);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
|
|
|
chs = substream->runtime->channels;
|
|
|
|
|
|
|
|
dataDCC2 = 0x2;
|
|
|
|
|
|
|
|
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE))
|
2010-09-07 18:27:25 +08:00
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_master_con_nid_7x,
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_DIGI_CONVERT_1,
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
|
|
|
/* set the stream id */
|
|
|
|
snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
|
|
|
|
AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
|
|
|
|
|
|
|
|
/* set the stream format */
|
|
|
|
snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
|
|
|
|
AC_VERB_SET_STREAM_FORMAT, format);
|
|
|
|
|
|
|
|
/* turn on again (if needed) */
|
|
|
|
/* enable and set the channel status audio/data flag */
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
if (codec->spdif_status_reset && (spdif->ctls & AC_DIG1_ENABLE)) {
|
2010-09-07 18:27:25 +08:00
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_master_con_nid_7x,
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_DIGI_CONVERT_1,
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
spdif->ctls & 0xff);
|
2010-09-07 18:27:25 +08:00
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_master_con_nid_7x,
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (chs == 2)
|
|
|
|
channel_id = 0;
|
|
|
|
else
|
|
|
|
channel_id = i * 2;
|
|
|
|
|
|
|
|
/* turn off SPDIF once;
|
|
|
|
*otherwise the IEC958 bits won't be updated
|
|
|
|
*/
|
|
|
|
if (codec->spdif_status_reset &&
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
(spdif->ctls & AC_DIG1_ENABLE))
|
2010-09-07 18:27:25 +08:00
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_con_nids_7x[i],
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_DIGI_CONVERT_1,
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
spdif->ctls & ~AC_DIG1_ENABLE & 0xff);
|
2010-09-07 18:27:25 +08:00
|
|
|
/* set the stream id */
|
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_con_nids_7x[i],
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_CHANNEL_STREAMID,
|
|
|
|
(stream_tag << 4) | channel_id);
|
|
|
|
/* set the stream format */
|
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_con_nids_7x[i],
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_STREAM_FORMAT,
|
|
|
|
format);
|
|
|
|
/* turn on again (if needed) */
|
|
|
|
/* enable and set the channel status audio/data flag */
|
|
|
|
if (codec->spdif_status_reset &&
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
(spdif->ctls & AC_DIG1_ENABLE)) {
|
2010-09-07 18:27:25 +08:00
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_con_nids_7x[i],
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_DIGI_CONVERT_1,
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
spdif->ctls & 0xff);
|
2010-09-07 18:27:25 +08:00
|
|
|
snd_hda_codec_write(codec,
|
|
|
|
nvhdmi_con_nids_7x[i],
|
|
|
|
0,
|
|
|
|
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-07 08:19:04 +08:00
|
|
|
nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
|
2010-09-07 18:27:25 +08:00
|
|
|
|
|
|
|
mutex_unlock(&codec->spdif_mutex);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-05-02 18:17:41 +08:00
|
|
|
static const struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
|
2010-09-07 18:27:25 +08:00
|
|
|
.substreams = 1,
|
|
|
|
.channels_min = 2,
|
|
|
|
.channels_max = 8,
|
|
|
|
.nid = nvhdmi_master_con_nid_7x,
|
|
|
|
.rates = SUPPORTED_RATES,
|
|
|
|
.maxbps = SUPPORTED_MAXBPS,
|
|
|
|
.formats = SUPPORTED_FORMATS,
|
|
|
|
.ops = {
|
|
|
|
.open = simple_playback_pcm_open,
|
|
|
|
.close = nvhdmi_8ch_7x_pcm_close,
|
|
|
|
.prepare = nvhdmi_8ch_7x_pcm_prepare
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
static int patch_nvhdmi_2ch(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec;
|
2012-06-15 20:34:42 +08:00
|
|
|
int err = patch_simple_hdmi(codec, nvhdmi_master_con_nid_7x,
|
|
|
|
nvhdmi_master_pin_nid_7x);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2010-09-07 18:27:25 +08:00
|
|
|
|
2012-06-15 20:38:31 +08:00
|
|
|
codec->patch_ops.init = nvhdmi_7x_init_2ch;
|
2012-06-15 20:34:42 +08:00
|
|
|
/* override the PCM rates, etc, as the codec doesn't give full list */
|
|
|
|
spec = codec->spec;
|
|
|
|
spec->pcm_playback.rates = SUPPORTED_RATES;
|
|
|
|
spec->pcm_playback.maxbps = SUPPORTED_MAXBPS;
|
|
|
|
spec->pcm_playback.formats = SUPPORTED_FORMATS;
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-08-01 18:17:41 +08:00
|
|
|
static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
|
|
|
int err = simple_playback_build_pcms(codec);
|
2013-03-13 21:40:31 +08:00
|
|
|
if (!err) {
|
|
|
|
struct hda_pcm *info = get_pcm_rec(spec, 0);
|
|
|
|
info->own_chmap = true;
|
|
|
|
}
|
2012-08-01 18:17:41 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hda_pcm *info;
|
2012-08-01 18:17:41 +08:00
|
|
|
struct snd_pcm_chmap *chmap;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = simple_playback_build_controls(codec);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
/* add channel maps */
|
2013-03-13 21:40:31 +08:00
|
|
|
info = get_pcm_rec(spec, 0);
|
|
|
|
err = snd_pcm_add_chmap_ctls(info->pcm,
|
2012-08-01 18:17:41 +08:00
|
|
|
SNDRV_PCM_STREAM_PLAYBACK,
|
|
|
|
snd_pcm_alt_chmaps, 8, 0, &chmap);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
switch (codec->preset->id) {
|
|
|
|
case 0x10de0002:
|
|
|
|
case 0x10de0003:
|
|
|
|
case 0x10de0005:
|
|
|
|
case 0x10de0006:
|
|
|
|
chmap->channel_mask = (1U << 2) | (1U << 8);
|
|
|
|
break;
|
|
|
|
case 0x10de0007:
|
|
|
|
chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec;
|
|
|
|
int err = patch_nvhdmi_2ch(codec);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
spec = codec->spec;
|
|
|
|
spec->multiout.max_channels = 8;
|
2012-06-15 20:34:42 +08:00
|
|
|
spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x;
|
2012-06-15 20:38:31 +08:00
|
|
|
codec->patch_ops.init = nvhdmi_7x_init_8ch;
|
2012-08-01 18:17:41 +08:00
|
|
|
codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms;
|
|
|
|
codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls;
|
2011-04-07 08:19:04 +08:00
|
|
|
|
|
|
|
/* Initialize the audio infoframe channel mask and checksum to something
|
|
|
|
* valid */
|
|
|
|
nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
|
|
|
|
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ATI-specific implementations
|
|
|
|
*
|
|
|
|
* FIXME: we may omit the whole this and use the generic code once after
|
|
|
|
* it's confirmed to work.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define ATIHDMI_CVT_NID 0x02 /* audio converter */
|
|
|
|
#define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */
|
|
|
|
|
|
|
|
static int atihdmi_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 hdmi_spec *spec = codec->spec;
|
2013-03-13 21:40:31 +08:00
|
|
|
struct hdmi_spec_per_cvt *per_cvt = get_cvt(spec, 0);
|
2010-09-07 18:27:25 +08:00
|
|
|
int chans = substream->runtime->channels;
|
|
|
|
int i, err;
|
|
|
|
|
|
|
|
err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format,
|
|
|
|
substream);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
2013-03-13 21:40:31 +08:00
|
|
|
snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
AC_VERB_SET_CVT_CHAN_COUNT, chans - 1);
|
2010-09-07 18:27:25 +08:00
|
|
|
/* FIXME: XXX */
|
|
|
|
for (i = 0; i < chans; i++) {
|
2013-03-13 21:40:31 +08:00
|
|
|
snd_hda_codec_write(codec, per_cvt->cvt_nid, 0,
|
2010-09-07 18:27:25 +08:00
|
|
|
AC_VERB_SET_HDMI_CHAN_SLOT,
|
|
|
|
(i << 4) | i);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int patch_atihdmi(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
struct hdmi_spec *spec;
|
2012-06-15 20:34:42 +08:00
|
|
|
int err = patch_simple_hdmi(codec, ATIHDMI_CVT_NID, ATIHDMI_PIN_NID);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
spec = codec->spec;
|
|
|
|
spec->pcm_playback.ops.prepare = atihdmi_playback_pcm_prepare;
|
2010-09-07 18:27:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-06-08 19:18:42 +08:00
|
|
|
/* VIA HDMI Implementation */
|
|
|
|
#define VIAHDMI_CVT_NID 0x02 /* audio converter1 */
|
|
|
|
#define VIAHDMI_PIN_NID 0x03 /* HDMI output pin1 */
|
|
|
|
|
|
|
|
static int patch_via_hdmi(struct hda_codec *codec)
|
|
|
|
{
|
2012-06-15 20:40:21 +08:00
|
|
|
return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);
|
2012-06-08 19:18:42 +08:00
|
|
|
}
|
2010-09-07 18:27:25 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* patch entries
|
|
|
|
*/
|
2011-05-02 18:17:41 +08:00
|
|
|
static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
|
2010-09-07 18:27:25 +08:00
|
|
|
{ .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
|
|
|
|
{ .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
|
|
|
|
{ .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
|
2010-12-05 08:34:15 +08:00
|
|
|
{ .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_generic_hdmi },
|
2010-09-07 18:27:25 +08:00
|
|
|
{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
|
|
|
|
{ .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
|
|
|
|
{ .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
|
|
|
|
{ .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
|
|
|
|
{ .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x },
|
ALSA: HDA: Unify HDMI hotplug handling.
This change unifies the initial handling of a pin's state with the code to
update a pin's state after a hotplug (unsolicited response) event. The
initial probing, and all updates, are now routed through hdmi_present_sense.
The stored PD and ELDV status is now always derived from GetPinSense verb
execution, and not from the data in the unsolicited response. This means:
a) The WAR for NVIDIA codec's UR.PD values ("old_pin_detect") can be
removed, since this only affected the no-longer-used unsolicited
response payload.
b) In turn, this means that most NVIDIA codecs can simply use
patch_generic_hdmi instead of having a custom variant just to set
old_pin_detect.
c) When PD && ELDV becomes true, no extra verbs are executed, because the
GetPinSense that was previously executed by snd_hdmi_get_eld (really,
hdmi_eld_valid) has simply moved into hdmi_present_sense.
d) When PD && ELDV becomes false, there is a single extra GetPinSense verb
executed for codecs where old_pin_detect wasn't set, i.e. some NVIDIA,
and all ATI/AMD and Intel codecs. I doubt this will be a performance
issue.
The new unified code in hdmi_present_sense also ensures that eld->eld_valid
is not set unless eld->monitor_present is also set. This protects against
potential invalid combinations of PD and ELDV received from HW, and
transitively from a graphics driver.
Also, print the derived PD/ELDV bits from hdmi_present_sense so the kernel
log always displays the actual state stored, which will differ from the
values in the unsolicited response for NVIDIA HW where old_pin_detect was
previously set.
Finally, a couple of small tweaks originally by Takashi:
* Clear the ELD content to zero before reading it, so that if it's not
read (i.e. when !(PD && ELDV)) it's in a known state.
* Don't show ELD fields in /proc ELD files when the ELD isn't valid.
The only possibility I can see for regression here is a codec where the
GetPinSense verb returns incorrect data. However, we're already exposed
to that, since that data is used (a) from hdmi_add_pin to set up the
initial pin state, and (b) within snd_hda_input_jack_report to query
a pin's presence value. As such, I don't believe any HW has bugs here.
Includes-changes-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-05-25 07:11:17 +08:00
|
|
|
{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0015, .name = "GPU 15 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0016, .name = "GPU 16 HDMI/DP", .patch = patch_generic_hdmi },
|
2011-03-03 19:46:13 +08:00
|
|
|
/* 17 is known to be absent */
|
ALSA: HDA: Unify HDMI hotplug handling.
This change unifies the initial handling of a pin's state with the code to
update a pin's state after a hotplug (unsolicited response) event. The
initial probing, and all updates, are now routed through hdmi_present_sense.
The stored PD and ELDV status is now always derived from GetPinSense verb
execution, and not from the data in the unsolicited response. This means:
a) The WAR for NVIDIA codec's UR.PD values ("old_pin_detect") can be
removed, since this only affected the no-longer-used unsolicited
response payload.
b) In turn, this means that most NVIDIA codecs can simply use
patch_generic_hdmi instead of having a custom variant just to set
old_pin_detect.
c) When PD && ELDV becomes true, no extra verbs are executed, because the
GetPinSense that was previously executed by snd_hdmi_get_eld (really,
hdmi_eld_valid) has simply moved into hdmi_present_sense.
d) When PD && ELDV becomes false, there is a single extra GetPinSense verb
executed for codecs where old_pin_detect wasn't set, i.e. some NVIDIA,
and all ATI/AMD and Intel codecs. I doubt this will be a performance
issue.
The new unified code in hdmi_present_sense also ensures that eld->eld_valid
is not set unless eld->monitor_present is also set. This protects against
potential invalid combinations of PD and ELDV received from HW, and
transitively from a graphics driver.
Also, print the derived PD/ELDV bits from hdmi_present_sense so the kernel
log always displays the actual state stored, which will differ from the
values in the unsolicited response for NVIDIA HW where old_pin_detect was
previously set.
Finally, a couple of small tweaks originally by Takashi:
* Clear the ELD content to zero before reading it, so that if it's not
read (i.e. when !(PD && ELDV)) it's in a known state.
* Don't show ELD fields in /proc ELD files when the ELD isn't valid.
The only possibility I can see for regression here is a codec where the
GetPinSense verb returns incorrect data. However, we're already exposed
to that, since that data is used (a) from hdmi_add_pin to set up the
initial pin state, and (b) within snd_hda_input_jack_report to query
a pin's presence value. As such, I don't believe any HW has bugs here.
Includes-changes-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-05-25 07:11:17 +08:00
|
|
|
{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_generic_hdmi },
|
2012-07-17 08:10:04 +08:00
|
|
|
{ .id = 0x10de0051, .name = "GPU 51 HDMI/DP", .patch = patch_generic_hdmi },
|
2013-07-13 02:01:37 +08:00
|
|
|
{ .id = 0x10de0060, .name = "GPU 60 HDMI/DP", .patch = patch_generic_hdmi },
|
2010-09-07 18:27:25 +08:00
|
|
|
{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
|
|
|
|
{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
|
2012-06-08 19:18:42 +08:00
|
|
|
{ .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi },
|
|
|
|
{ .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi },
|
|
|
|
{ .id = 0x11069f84, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x11069f85, .name = "VX11 HDMI/DP", .patch = patch_generic_hdmi },
|
2010-09-07 18:27:25 +08:00
|
|
|
{ .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi },
|
2011-05-20 15:35:43 +08:00
|
|
|
{ .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
|
2012-06-13 10:23:52 +08:00
|
|
|
{ .id = 0x80862807, .name = "Haswell HDMI", .patch = patch_generic_hdmi },
|
2012-02-23 15:07:44 +08:00
|
|
|
{ .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi },
|
2010-09-07 18:27:25 +08:00
|
|
|
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
|
|
|
|
{} /* terminator */
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:1002793c");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10027919");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:1002791a");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:1002aa01");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10951390");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10951392");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0002");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0003");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0005");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0006");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0007");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de000a");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de000b");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de000c");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de000d");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0010");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0011");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0012");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0013");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0014");
|
2011-03-03 19:46:13 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0015");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0016");
|
2010-09-07 18:27:25 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0018");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0019");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de001a");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de001b");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de001c");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0040");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0041");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0042");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0043");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0044");
|
2012-07-17 08:10:04 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0051");
|
2013-07-13 02:01:37 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0060");
|
2010-09-07 18:27:25 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de0067");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:10de8001");
|
2012-06-08 19:18:42 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:11069f80");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:11069f81");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:11069f84");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:11069f85");
|
2010-09-07 18:27:25 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:17e80047");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80860054");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862801");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862802");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862803");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862804");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862805");
|
2011-05-20 15:35:43 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862806");
|
2012-06-13 10:23:52 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862807");
|
2012-02-23 15:07:44 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:80862880");
|
2010-09-07 18:27:25 +08:00
|
|
|
MODULE_ALIAS("snd-hda-codec-id:808629fb");
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_DESCRIPTION("HDMI HD-audio codec");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-intelhdmi");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-nvhdmi");
|
|
|
|
MODULE_ALIAS("snd-hda-codec-atihdmi");
|
|
|
|
|
|
|
|
static struct hda_codec_preset_list intel_list = {
|
|
|
|
.preset = snd_hda_preset_hdmi,
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init patch_hdmi_init(void)
|
|
|
|
{
|
|
|
|
return snd_hda_add_codec_preset(&intel_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit patch_hdmi_exit(void)
|
|
|
|
{
|
|
|
|
snd_hda_delete_codec_preset(&intel_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(patch_hdmi_init)
|
|
|
|
module_exit(patch_hdmi_exit)
|