[RFC,v2,00/11] Enable HDA Codec support on Intel Platforms (Series2)
diff mbox

Message ID 85DFEED57DC57344B2483EF7BF8CB60579AD52D3@BGSMSX104.gar.corp.intel.com
State New
Headers show

Commit Message

Ughreja, Rakesh A Dec. 12, 2017, 4:37 p.m. UTC
>-----Original Message-----
>From: Takashi Iwai [mailto:tiwai@suse.de]
>Sent: Tuesday, December 12, 2017 12:19 AM
>To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>
>Cc: alsa-devel@alsa-project.org; broonie@kernel.org;
>liam.r.girdwood@linux.intel.com; pierre-louis.bossart@linux.intel.com; Koul,
>Vinod <vinod.koul@intel.com>; Patches Audio <patches.audio@intel.com>
>Subject: Re: [RFC v2 00/11] Enable HDA Codec support on Intel Platforms
>(Series2)

>
>The registration should be triggered from the top-level, i.e. the
>controller driver, once after all codecs get probed.  Otherwise, it
>becomes racy.  The user-space will start poking the device before all
>the stuff becomes ready.

Thank you very much, I understand now.

>
>That said, at the point when the codec is probed, the card shouldn't
>be registered yet.  The card gets registered after the all components
>are bound and become ready -- which is done a single
>snd_card_register() call.  At this point, the access points to
>user-space are provided.

So based on your suggestion when I relooked at the code, I could
remove the new function that I added. I could completely reuse the 
existing function with little change.

Does it look okay ?

Following is the patch, which I tested and it works for me.
I will include this in next series but for now it's only for quick reference.

I am calling this API from the hdac_hda codec driver with argument
HDA_DEV_ASOC to make sure that it does not register with the bus
again. I am not able to call this API from ASoC Platform driver because
I don't have snd_card pointer at the time of machine driver probe.

Following is the patch. 
---------------------------
Modify snd_hda_codec_new API so that it can work for legacy as well as
ASoC codec drivers. The API takes an additional argument dev_type as
HDA_DEV_LEGACY or HDA_DEV_ASOC to distinguish the caller.

Signed-off-by: Rakesh Ughreja <rakesh.a.ughreja@intel.com>
---
 sound/pci/hda/hda_codec.c      | 30 +++++++++++++++++++-----------
 sound/pci/hda/hda_codec.h      |  3 ++-
 sound/pci/hda/hda_controller.c |  2 +-
 3 files changed, 22 insertions(+), 13 deletions(-)

Comments

Takashi Iwai Dec. 12, 2017, 4:50 p.m. UTC | #1
On Tue, 12 Dec 2017 17:37:56 +0100,
Ughreja, Rakesh A wrote:
> 
> 
> 
> >-----Original Message-----
> >From: Takashi Iwai [mailto:tiwai@suse.de]
> >Sent: Tuesday, December 12, 2017 12:19 AM
> >To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>
> >Cc: alsa-devel@alsa-project.org; broonie@kernel.org;
> >liam.r.girdwood@linux.intel.com; pierre-louis.bossart@linux.intel.com; Koul,
> >Vinod <vinod.koul@intel.com>; Patches Audio <patches.audio@intel.com>
> >Subject: Re: [RFC v2 00/11] Enable HDA Codec support on Intel Platforms
> >(Series2)
> 
> >
> >The registration should be triggered from the top-level, i.e. the
> >controller driver, once after all codecs get probed.  Otherwise, it
> >becomes racy.  The user-space will start poking the device before all
> >the stuff becomes ready.
> 
> Thank you very much, I understand now.
> 
> >
> >That said, at the point when the codec is probed, the card shouldn't
> >be registered yet.  The card gets registered after the all components
> >are bound and become ready -- which is done a single
> >snd_card_register() call.  At this point, the access points to
> >user-space are provided.
> 
> So based on your suggestion when I relooked at the code, I could
> remove the new function that I added. I could completely reuse the 
> existing function with little change.
> 
> Does it look okay ?

Lesser, better :)


> Following is the patch, which I tested and it works for me.
> I will include this in next series but for now it's only for quick reference.
> 
> I am calling this API from the hdac_hda codec driver with argument
> HDA_DEV_ASOC to make sure that it does not register with the bus
> again. I am not able to call this API from ASoC Platform driver because
> I don't have snd_card pointer at the time of machine driver probe.
> 
> Following is the patch. 
> ---------------------------
> Modify snd_hda_codec_new API so that it can work for legacy as well as
> ASoC codec drivers. The API takes an additional argument dev_type as
> HDA_DEV_LEGACY or HDA_DEV_ASOC to distinguish the caller.

The idea looks good, but I'd prefer different functions instead of
mutating the behavior depending on the flag.  i.e. keep
snd_hda_codec_new(), and introduce another API (snd_hda_codec_init()
or whatever).  ASoC driver can call the latter while the legacy driver
keeps calling the former.

This would factor out the allocation and snd_hdac_device_init() calls
from the old snd_hda_codec_new() to a new snd_hda_codec_new().
snd_hda_codec_init() would do the rest.  snd_hda_codec_new() calls
snd_hda_codec_init() at the end of the function.

Does this sound good for you?


thanks,

Takashi

> 
> Signed-off-by: Rakesh Ughreja <rakesh.a.ughreja@intel.com>
> ---
>  sound/pci/hda/hda_codec.c      | 30 +++++++++++++++++++-----------
>  sound/pci/hda/hda_codec.h      |  3 ++-
>  sound/pci/hda/hda_controller.c |  2 +-
>  3 files changed, 22 insertions(+), 13 deletions(-)
> 
> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
> index 085fd9e..252779c 100644
> --- a/sound/pci/hda/hda_codec.c
> +++ b/sound/pci/hda/hda_codec.c
> @@ -865,7 +865,8 @@ static void snd_hda_codec_dev_release(struct device *dev)
>   * Returns 0 if successful, or a negative error code.
>   */
>  int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
> -		      unsigned int codec_addr, struct hda_codec **codecp)
> +		      unsigned int codec_addr, struct hda_codec **codecp,
> +			unsigned int dev_type)
>  {
>  	struct hda_codec *codec;
>  	char component[31];
> @@ -882,20 +883,27 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
>  	if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
>  		return -EINVAL;
>  
> -	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
> -	if (!codec)
> -		return -ENOMEM;
> +	if (dev_type == HDA_DEV_LEGACY) {
>  
> -	sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
> -	err = snd_hdac_device_init(&codec->core, &bus->core, component,
> -				   codec_addr);
> -	if (err < 0) {
> -		kfree(codec);
> -		return err;
> +		codec = kzalloc(sizeof(*codec), GFP_KERNEL);
> +		if (!codec)
> +			return -ENOMEM;
> +
> +		sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
> +		err = snd_hdac_device_init(&codec->core, &bus->core, component,
> +						codec_addr);
> +		if (err < 0) {
> +			kfree(codec);
> +			return err;
> +		}
> +
> +		codec->core.type = HDA_DEV_LEGACY;
> +
> +	} else {
> +		codec = *codecp;
>  	}
>  
>  	codec->core.dev.release = snd_hda_codec_dev_release;
> -	codec->core.type = HDA_DEV_LEGACY;
>  	codec->core.exec_verb = codec_exec_verb;
>  
>  	codec->bus = bus;
> diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
> index d3099db..92815b7 100644
> --- a/sound/pci/hda/hda_codec.h
> +++ b/sound/pci/hda/hda_codec.h
> @@ -306,7 +306,8 @@ struct hda_codec {
>   * constructors
>   */
>  int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
> -		      unsigned int codec_addr, struct hda_codec **codecp);
> +			unsigned int codec_addr, struct hda_codec **codecp,
> +			unsigned int dev_type);
>  int snd_hda_codec_configure(struct hda_codec *codec);
>  int snd_hda_codec_update_widgets(struct hda_codec *codec);
>  
> diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
> index d1eb148..ec887d7 100644
> --- a/sound/pci/hda/hda_controller.c
> +++ b/sound/pci/hda/hda_controller.c
> @@ -1318,7 +1318,7 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots)
>  	for (c = 0; c < max_slots; c++) {
>  		if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
>  			struct hda_codec *codec;
> -			err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec);
> +			err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec, HDA_DEV_LEGACY);
>  			if (err < 0)
>  				continue;
>  			codec->jackpoll_interval = get_jackpoll_interval(chip);
> -- 
> 2.7.4
>
Joël Krähemann Dec. 12, 2017, 6:21 p.m. UTC | #2
Hi,
Where is your code located? Since I have got a macbook pro 2016 and I
believe this feature is a prerequisite to get any sound working.
I would love to test it with my cirrus logic 8409 HDA soundcard.

Bests,
Joël


On Tue, Dec 12, 2017 at 5:37 PM, Ughreja, Rakesh A
<rakesh.a.ughreja@intel.com> wrote:
>
>
>>-----Original Message-----
>>From: Takashi Iwai [mailto:tiwai@suse.de]
>>Sent: Tuesday, December 12, 2017 12:19 AM
>>To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>
>>Cc: alsa-devel@alsa-project.org; broonie@kernel.org;
>>liam.r.girdwood@linux.intel.com; pierre-louis.bossart@linux.intel.com; Koul,
>>Vinod <vinod.koul@intel.com>; Patches Audio <patches.audio@intel.com>
>>Subject: Re: [RFC v2 00/11] Enable HDA Codec support on Intel Platforms
>>(Series2)
>
>>
>>The registration should be triggered from the top-level, i.e. the
>>controller driver, once after all codecs get probed.  Otherwise, it
>>becomes racy.  The user-space will start poking the device before all
>>the stuff becomes ready.
>
> Thank you very much, I understand now.
>
>>
>>That said, at the point when the codec is probed, the card shouldn't
>>be registered yet.  The card gets registered after the all components
>>are bound and become ready -- which is done a single
>>snd_card_register() call.  At this point, the access points to
>>user-space are provided.
>
> So based on your suggestion when I relooked at the code, I could
> remove the new function that I added. I could completely reuse the
> existing function with little change.
>
> Does it look okay ?
>
> Following is the patch, which I tested and it works for me.
> I will include this in next series but for now it's only for quick reference.
>
> I am calling this API from the hdac_hda codec driver with argument
> HDA_DEV_ASOC to make sure that it does not register with the bus
> again. I am not able to call this API from ASoC Platform driver because
> I don't have snd_card pointer at the time of machine driver probe.
>
> Following is the patch.
> ---------------------------
> Modify snd_hda_codec_new API so that it can work for legacy as well as
> ASoC codec drivers. The API takes an additional argument dev_type as
> HDA_DEV_LEGACY or HDA_DEV_ASOC to distinguish the caller.
>
> Signed-off-by: Rakesh Ughreja <rakesh.a.ughreja@intel.com>
> ---
>  sound/pci/hda/hda_codec.c      | 30 +++++++++++++++++++-----------
>  sound/pci/hda/hda_codec.h      |  3 ++-
>  sound/pci/hda/hda_controller.c |  2 +-
>  3 files changed, 22 insertions(+), 13 deletions(-)
>
> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
> index 085fd9e..252779c 100644
> --- a/sound/pci/hda/hda_codec.c
> +++ b/sound/pci/hda/hda_codec.c
> @@ -865,7 +865,8 @@ static void snd_hda_codec_dev_release(struct device *dev)
>   * Returns 0 if successful, or a negative error code.
>   */
>  int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
> -                     unsigned int codec_addr, struct hda_codec **codecp)
> +                     unsigned int codec_addr, struct hda_codec **codecp,
> +                       unsigned int dev_type)
>  {
>         struct hda_codec *codec;
>         char component[31];
> @@ -882,20 +883,27 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
>         if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
>                 return -EINVAL;
>
> -       codec = kzalloc(sizeof(*codec), GFP_KERNEL);
> -       if (!codec)
> -               return -ENOMEM;
> +       if (dev_type == HDA_DEV_LEGACY) {
>
> -       sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
> -       err = snd_hdac_device_init(&codec->core, &bus->core, component,
> -                                  codec_addr);
> -       if (err < 0) {
> -               kfree(codec);
> -               return err;
> +               codec = kzalloc(sizeof(*codec), GFP_KERNEL);
> +               if (!codec)
> +                       return -ENOMEM;
> +
> +               sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
> +               err = snd_hdac_device_init(&codec->core, &bus->core, component,
> +                                               codec_addr);
> +               if (err < 0) {
> +                       kfree(codec);
> +                       return err;
> +               }
> +
> +               codec->core.type = HDA_DEV_LEGACY;
> +
> +       } else {
> +               codec = *codecp;
>         }
>
>         codec->core.dev.release = snd_hda_codec_dev_release;
> -       codec->core.type = HDA_DEV_LEGACY;
>         codec->core.exec_verb = codec_exec_verb;
>
>         codec->bus = bus;
> diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
> index d3099db..92815b7 100644
> --- a/sound/pci/hda/hda_codec.h
> +++ b/sound/pci/hda/hda_codec.h
> @@ -306,7 +306,8 @@ struct hda_codec {
>   * constructors
>   */
>  int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
> -                     unsigned int codec_addr, struct hda_codec **codecp);
> +                       unsigned int codec_addr, struct hda_codec **codecp,
> +                       unsigned int dev_type);
>  int snd_hda_codec_configure(struct hda_codec *codec);
>  int snd_hda_codec_update_widgets(struct hda_codec *codec);
>
> diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
> index d1eb148..ec887d7 100644
> --- a/sound/pci/hda/hda_controller.c
> +++ b/sound/pci/hda/hda_controller.c
> @@ -1318,7 +1318,7 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots)
>         for (c = 0; c < max_slots; c++) {
>                 if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
>                         struct hda_codec *codec;
> -                       err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec);
> +                       err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec, HDA_DEV_LEGACY);
>                         if (err < 0)
>                                 continue;
>                         codec->jackpoll_interval = get_jackpoll_interval(chip);
> --
> 2.7.4
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Ughreja, Rakesh A Dec. 12, 2017, 6:25 p.m. UTC | #3
>-----Original Message-----
>From: alsa-devel-bounces@alsa-project.org [mailto:alsa-devel-bounces@alsa-
>project.org] On Behalf Of Takashi Iwai
>Sent: Tuesday, December 12, 2017 10:21 PM
>To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>
>Cc: alsa-devel@alsa-project.org; Koul, Vinod <vinod.koul@intel.com>; pierre-
>louis.bossart@linux.intel.com; liam.r.girdwood@linux.intel.com; Patches Audio
><patches.audio@intel.com>; broonie@kernel.org
>Subject: Re: [alsa-devel] [RFC v2 00/11] Enable HDA Codec support on Intel
>Platforms (Series2)
>


>
>The idea looks good, but I'd prefer different functions instead of
>mutating the behavior depending on the flag.  i.e. keep
>snd_hda_codec_new(), and introduce another API (snd_hda_codec_init()
>or whatever).  ASoC driver can call the latter while the legacy driver
>keeps calling the former.
>
>This would factor out the allocation and snd_hdac_device_init() calls
>from the old snd_hda_codec_new() to a new snd_hda_codec_new().
>snd_hda_codec_init() would do the rest.  snd_hda_codec_new() calls
>snd_hda_codec_init() at the end of the function.
>
>Does this sound good for you?

I think I got this :) Thanks. Here is the skeleton code.
I split the existing function snd_hda_codec_new into two parts.

1. snd_hda_codec_device_init()
2. snd_hda_codec_device_new()

So the new body of existing function snd_hda_codec_new looks like.

int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,               
                      unsigned int codec_addr, struct hda_codec **codecp)       
{                                                                               
        int ret;                                                                
                                                                                
        ret = snd_hda_codec_device_init(bus, card, codec_addr, codecp);         
        if (ret < 0)                                                            
                return ret;                                                     
                                                                                
        return snd_hda_codec_device_new(bus, card, codec_addr, *codecp);        
}

The ASoC driver would call only snd_hda_codec_device_new.
If you have any suggestions for the function names, I can change it before
I post the next series.

Now switching over to the id_table problem. In the current series it is accessed
using extern, in the patch_realtek.c file. So we really have two different
KO files. One for legacy HDA driver and second for ASoC HDA driver.

Would you like to keep them as two separate KO files or prefer to have a
single KO file ?
Ughreja, Rakesh A Dec. 12, 2017, 6:40 p.m. UTC | #4
>-----Original Message-----

>From: alsa-devel-bounces@alsa-project.org [mailto:alsa-devel-bounces@alsa-

>project.org] On Behalf Of Joël Krähemann

>Sent: Tuesday, December 12, 2017 11:52 PM

>To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>

>Cc: alsa-devel@alsa-project.org; Takashi Iwai <tiwai@suse.de>; pierre-

>louis.bossart@linux.intel.com; Patches Audio <patches.audio@intel.com>;

>liam.r.girdwood@linux.intel.com; Koul, Vinod <vinod.koul@intel.com>;

>broonie@kernel.org

>Subject: Re: [alsa-devel] [RFC v2 00/11] Enable HDA Codec support on Intel

>Platforms (Series2)

>

>Hi,

>Where is your code located? Since I have got a macbook pro 2016 and I

>believe this feature is a prerequisite to get any sound working.

>I would love to test it with my cirrus logic 8409 HDA soundcard.


My last series was rebased on top of Mark's for-next tree. You would need
Topology file, which I can send via email. But before I do that I want to confirm
if you have the right things enabled.

Do you know if it is based on 6th Generation (SKL) or 7th Generation(KBL) of Intel core ?
You will need to download the DSP Firmware binary file based on this.
Also I am not sure if the DSP functionality is enabled on the MAC systems. If you compile
snd-hda-core.ko in debug mode, it prints the capabilities. I can check that from the logs.

Regards,
Rakesh
Joël Krähemann Dec. 12, 2017, 6:51 p.m. UTC | #5
Hi,
I am pretty sure it contains this integrated circuit: MAX98357BEWL
It is a DSP. Why is a need for firmware?

It is a Intel Core i5-6360U

https://bugzilla.kernel.org/show_bug.cgi?id=195671

Bests,
Joël

On Tue, Dec 12, 2017 at 7:40 PM, Ughreja, Rakesh A
<rakesh.a.ughreja@intel.com> wrote:
>
>
>>-----Original Message-----
>>From: alsa-devel-bounces@alsa-project.org [mailto:alsa-devel-bounces@alsa-
>>project.org] On Behalf Of Joël Krähemann
>>Sent: Tuesday, December 12, 2017 11:52 PM
>>To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>
>>Cc: alsa-devel@alsa-project.org; Takashi Iwai <tiwai@suse.de>; pierre-
>>louis.bossart@linux.intel.com; Patches Audio <patches.audio@intel.com>;
>>liam.r.girdwood@linux.intel.com; Koul, Vinod <vinod.koul@intel.com>;
>>broonie@kernel.org
>>Subject: Re: [alsa-devel] [RFC v2 00/11] Enable HDA Codec support on Intel
>>Platforms (Series2)
>>
>>Hi,
>>Where is your code located? Since I have got a macbook pro 2016 and I
>>believe this feature is a prerequisite to get any sound working.
>>I would love to test it with my cirrus logic 8409 HDA soundcard.
>
> My last series was rebased on top of Mark's for-next tree. You would need
> Topology file, which I can send via email. But before I do that I want to confirm
> if you have the right things enabled.
>
> Do you know if it is based on 6th Generation (SKL) or 7th Generation(KBL) of Intel core ?
> You will need to download the DSP Firmware binary file based on this.
> Also I am not sure if the DSP functionality is enabled on the MAC systems. If you compile
> snd-hda-core.ko in debug mode, it prints the capabilities. I can check that from the logs.
>
> Regards,
> Rakesh
>
Ughreja, Rakesh A Dec. 13, 2017, 5:22 a.m. UTC | #6
>-----Original Message-----

>From: Joël Krähemann [mailto:jkraehemann@gmail.com]

>Sent: Wednesday, December 13, 2017 12:21 AM

>To: Ughreja, Rakesh A <rakesh.a.ughreja@intel.com>

>Cc: alsa-devel@alsa-project.org; Takashi Iwai <tiwai@suse.de>; pierre-

>louis.bossart@linux.intel.com; Patches Audio <patches.audio@intel.com>;

>liam.r.girdwood@linux.intel.com; Koul, Vinod <vinod.koul@intel.com>;

>broonie@kernel.org

>Subject: Re: [alsa-devel] [RFC v2 00/11] Enable HDA Codec support on Intel

>Platforms (Series2)

>

>Hi,

>I am pretty sure it contains this integrated circuit: MAX98357BEWL

>It is a DSP. Why is a need for firmware?

>

>It is a Intel Core i5-6360U

>

>https://bugzilla.kernel.org/show_bug.cgi?id=195671


After looking at the Bugzilla it looks like you are looking for something
else.

Recent Intel platforms contains HD Audio controllers with Integrated 
DSPs. Intel releases firmware which runs on this DSPs. You can connect
various codecs e.g. I2S, HDA etc. Support for I2S based codecs is
already available in the kernel today. However support for HDA codecs
connected via DSP is not yet upstreamed. I am trying to do it.

In your case the DSP functionality is part of the Maxim HDA codec.
My work is to enable the DSP functionality on the Intel SoC. So it
may not help you directly.

Regards,
Rakesh

Patch
diff mbox

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 085fd9e..252779c 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -865,7 +865,8 @@  static void snd_hda_codec_dev_release(struct device *dev)
  * Returns 0 if successful, or a negative error code.
  */
 int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
-		      unsigned int codec_addr, struct hda_codec **codecp)
+		      unsigned int codec_addr, struct hda_codec **codecp,
+			unsigned int dev_type)
 {
 	struct hda_codec *codec;
 	char component[31];
@@ -882,20 +883,27 @@  int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
 	if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
 		return -EINVAL;
 
-	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
-	if (!codec)
-		return -ENOMEM;
+	if (dev_type == HDA_DEV_LEGACY) {
 
-	sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
-	err = snd_hdac_device_init(&codec->core, &bus->core, component,
-				   codec_addr);
-	if (err < 0) {
-		kfree(codec);
-		return err;
+		codec = kzalloc(sizeof(*codec), GFP_KERNEL);
+		if (!codec)
+			return -ENOMEM;
+
+		sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
+		err = snd_hdac_device_init(&codec->core, &bus->core, component,
+						codec_addr);
+		if (err < 0) {
+			kfree(codec);
+			return err;
+		}
+
+		codec->core.type = HDA_DEV_LEGACY;
+
+	} else {
+		codec = *codecp;
 	}
 
 	codec->core.dev.release = snd_hda_codec_dev_release;
-	codec->core.type = HDA_DEV_LEGACY;
 	codec->core.exec_verb = codec_exec_verb;
 
 	codec->bus = bus;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index d3099db..92815b7 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -306,7 +306,8 @@  struct hda_codec {
  * constructors
  */
 int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
-		      unsigned int codec_addr, struct hda_codec **codecp);
+			unsigned int codec_addr, struct hda_codec **codecp,
+			unsigned int dev_type);
 int snd_hda_codec_configure(struct hda_codec *codec);
 int snd_hda_codec_update_widgets(struct hda_codec *codec);
 
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index d1eb148..ec887d7 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -1318,7 +1318,7 @@  int azx_probe_codecs(struct azx *chip, unsigned int max_slots)
 	for (c = 0; c < max_slots; c++) {
 		if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) {
 			struct hda_codec *codec;
-			err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec);
+			err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec, HDA_DEV_LEGACY);
 			if (err < 0)
 				continue;
 			codec->jackpoll_interval = get_jackpoll_interval(chip);