diff mbox

Intel HDA / ALC662 analog surround problem

Message ID 54f58df6.3dd80617.bm000@wupperonline.de (mailing list archive)
State New, archived
Headers show

Commit Message

Ingo Brueckl March 3, 2015, 9:36 a.m. UTC
Raymond,

I'm not familiar with hardware, so I had some difficulties to understand
what's going on here, but then I got really curious. So I grabbed an ALC662
datasheet and studied the block diagram. Now I think that I'm beginning to
understand.

>> >> > [    0.655493] sound hdaudioC1D0: autoconfig: line_outs=1 (0x14/0x0/0x0/0x0/0x0) type:line
>> >> > [    0.655494] sound hdaudioC1D0:    speaker_outs=1 (0x15/0x0/0x0/0x0/0x0)
>> >> > [    0.655495] sound hdaudioC1D0:    hp_outs=1 (0x1b/0x0/0x0/0x0/0x0)
>> >> > [    0.655496] sound hdaudioC1D0:    mono: mono_out=0x0
>> >> > [    0.655496] sound hdaudioC1D0:    dig-out=0x1e/0x0
>> >> > [    0.655497] sound hdaudioC1D0:    inputs:
>> >> > [    0.655498] sound hdaudioC1D0:      Front Mic=0x19
>> >> > [    0.655499] sound hdaudioC1D0:      Rear Mic=0x18
>> >> > [    0.655499] sound hdaudioC1D0:      Line=0x1a
>> >>
>> >> > This is a known bug of hda_generic.c for those desktop with internal
>> >> > speaker and three audio jacks at rear panel (e.g. those lenovo
>> >> > thinkcenter with alc66x codec)
>> >>
>> >> > The driver prefer to assign volume control/dac to headphone, line out and
>> >> > internal speaker instead of line out and the other two multi io jacks
>>
>> > or You need to increase BAD_MULTI_IO from 0x120 to 0x4120 since
>> > BAD_NO_DAC 0x4000 for the driver to select config with mio=1
>>

>==> lo_type=0, wired=1, mio=1, badness=0x352
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
>   out path: depth=3 '02:0c:14'
> hp_outs = 1b/0/0/0 : 2/0/0/0
>   hp  path: depth=3 '02:0c:1b'
> spk_outs = 15/0/0/0 : 3/0/0/0
>   spk path: depth=3 '03:0d:15'
>==> lo_type=0, wired=1, mio=0, badness=0x120
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
>   out path: depth=3 '02:0c:14'
> hp_outs = 1b/0/0/0 : 4/0/0/0
>   hp  path: depth=3 '04:0e:1b'
> spk_outs = 15/0/0/0 : 3/0/0/0
>   spk path: depth=3 '03:0d:15'
> send: NID=0x18, VERB=0xf00(get_parameters), PARM=0x12(amp_out_cap)
> receive: 0x80000000
>==> lo_type=0, wired=0, mio=1, badness=0x4112
> multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
>   out path: depth=3 '02:0c:14'
> multi_ios(2) = 1a/18 : 3/4
>   mio path: depth=3 '03:0d:1a'
>   mio path: depth=3 '04:0e:18'
> hp_outs = 1b/0/0/0 : 2/0/0/0
>   hp  path: depth=3 '02:0c:1b'
> spk_outs = 15/0/0/0 : 0/0/0/0
>==> lo_type=0, wired=0, mio=0, badness=0x4120
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
>   out path: depth=3 '02:0c:14'
> hp_outs = 1b/0/0/0 : 3/0/0/0
>   hp  path: depth=3 '03:0d:1b'
> spk_outs = 15/0/0/0 : 0/0/0/0
>==> restoring best_cfg
>==> Best config: lo_type=0, wired=1, mio=0
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
>   out path: depth=3 '02:0c:14'
> hp_outs = 1b/0/0/0 : 4/0/0/0
>   hp  path: depth=3 '04:0e:1b'
> spk_outs = 15/0/0/0 : 3/0/0/0
>   spk path: depth=3 '03:0d:15'

> The current driver select config with smallest badness
> You need an ad hoc check of increasing the badness due to multi io cannot
> be assigned  for those realtek alc66x codecs with 3stack and internal
> speaker

I think I've figured out how to safely perform a private kernel patch for it.


Now I'm getting the favored config:

==> lo_type=0, wired=1, mio=1, badness=0x352
multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
hp_outs = 1b/0/0/0 : 2/0/0/0
spk_outs = 15/0/0/0 : 3/0/0/0
==> lo_type=0, wired=1, mio=0, badness=0x120
multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
hp_outs = 1b/0/0/0 : 4/0/0/0
spk_outs = 15/0/0/0 : 3/0/0/0
==> lo_type=0, wired=0, mio=1, badness=0x112
multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
multi_ios(2) = 1a/18 : 3/4
hp_outs = 1b/0/0/0 : 2/0/0/0
spk_outs = 15/0/0/0 : 0/0/0/0
==> lo_type=0, wired=0, mio=0, badness=0x120
multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
hp_outs = 1b/0/0/0 : 3/0/0/0
spk_outs = 15/0/0/0 : 0/0/0/0
==> restoring best_cfg
==> Best config: lo_type=0, wired=0, mio=1
multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
multi_ios(2) = 1a/18 : 3/4
hp_outs = 1b/0/0/0 : 2/0/0/0
spk_outs = 15/0/0/0 : 0/0/0/0

> > The master volume control affects the line out volume (which is named PCM,
> > btw), but no other output. Muting the master, however, affects all outputs.
> >
> > After changing to 4ch or 6ch, the PCM (line out) volume control acts as a
> > "master" for surround and center/lfe.

> Seem "master playback volume" is not the correct name when using surround
> 5.1 and your config lost the virtual master playback volume

It seems that this is fixable. Patch will follow.

By the way, there is one thing I still don't understand. After booting there
is no "PCM Playback Volume" control in alsamixer. As soon as I've played some
wav file, it appears. Where does it come from, i.e. is it created by kernel
or alsa-lib/utils and why?

Ingo

Comments

Raymond Yau March 3, 2015, 1:41 p.m. UTC | #1
>
> I'm not familiar with hardware, so I had some difficulties to understand
> what's going on here, but then I got really curious. So I grabbed an
ALC662
> datasheet and studied the block diagram. Now I think that I'm beginning to
> understand.
>
> >> >> > [    0.655493] sound hdaudioC1D0: autoconfig: line_outs=1
(0x14/0x0/0x0/0x0/0x0) type:line
> >> >> > [    0.655494] sound hdaudioC1D0:    speaker_outs=1
(0x15/0x0/0x0/0x0/0x0)
> >> >> > [    0.655495] sound hdaudioC1D0:    hp_outs=1
(0x1b/0x0/0x0/0x0/0x0)
> >> >> > [    0.655496] sound hdaudioC1D0:    mono: mono_out=0x0
> >> >> > [    0.655496] sound hdaudioC1D0:    dig-out=0x1e/0x0
> >> >> > [    0.655497] sound hdaudioC1D0:    inputs:
> >> >> > [    0.655498] sound hdaudioC1D0:      Front Mic=0x19
> >> >> > [    0.655499] sound hdaudioC1D0:      Rear Mic=0x18
> >> >> > [    0.655499] sound hdaudioC1D0:      Line=0x1a
> >> >>
> >> >> > This is a known bug of hda_generic.c for those desktop with
internal
> >> >> > speaker and three audio jacks at rear panel (e.g. those lenovo
> >> >> > thinkcenter with alc66x codec)
> >> >>
> >> >> > The driver prefer to assign volume control/dac to headphone, line
out and
> >> >> > internal speaker instead of line out and the other two multi io
jacks
> >>
> >> > or You need to increase BAD_MULTI_IO from 0x120 to 0x4120 since
> >> > BAD_NO_DAC 0x4000 for the driver to select config with mio=1
> >>
>
> >==> lo_type=0, wired=1, mio=1, badness=0x352
> > multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> >   out path: depth=3 '02:0c:14'
> > hp_outs = 1b/0/0/0 : 2/0/0/0
> >   hp  path: depth=3 '02:0c:1b'
> > spk_outs = 15/0/0/0 : 3/0/0/0
> >   spk path: depth=3 '03:0d:15'
> >==> lo_type=0, wired=1, mio=0, badness=0x120
> > multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> >   out path: depth=3 '02:0c:14'
> > hp_outs = 1b/0/0/0 : 4/0/0/0
> >   hp  path: depth=3 '04:0e:1b'
> > spk_outs = 15/0/0/0 : 3/0/0/0
> >   spk path: depth=3 '03:0d:15'
> > send: NID=0x18, VERB=0xf00(get_parameters), PARM=0x12(amp_out_cap)
> > receive: 0x80000000
> >==> lo_type=0, wired=0, mio=1, badness=0x4112
> > multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
> >   out path: depth=3 '02:0c:14'
> > multi_ios(2) = 1a/18 : 3/4
> >   mio path: depth=3 '03:0d:1a'
> >   mio path: depth=3 '04:0e:18'
> > hp_outs = 1b/0/0/0 : 2/0/0/0
> >   hp  path: depth=3 '02:0c:1b'
> > spk_outs = 15/0/0/0 : 0/0/0/0
> >==> lo_type=0, wired=0, mio=0, badness=0x4120
> > multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> >   out path: depth=3 '02:0c:14'
> > hp_outs = 1b/0/0/0 : 3/0/0/0
> >   hp  path: depth=3 '03:0d:1b'
> > spk_outs = 15/0/0/0 : 0/0/0/0
> >==> restoring best_cfg
> >==> Best config: lo_type=0, wired=1, mio=0
> > multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> >   out path: depth=3 '02:0c:14'
> > hp_outs = 1b/0/0/0 : 4/0/0/0
> >   hp  path: depth=3 '04:0e:1b'
> > spk_outs = 15/0/0/0 : 3/0/0/0
> >   spk path: depth=3 '03:0d:15'
>
> > The current driver select config with smallest badness
> > You need an ad hoc check of increasing the badness due to multi io
cannot
> > be assigned  for those realtek alc66x codecs with 3stack and internal
> > speaker
>
> I think I've figured out how to safely perform a private kernel patch for
it.
>
> diff -Nur a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
> --- a/sound/pci/hda/hda_generic.c       2015-02-11 08:01:12.000000000
+0100
> +++ b/sound/pci/hda/hda_generic.c       2015-03-02 22:57:34.799192329
+0100
> @@ -1233,7 +1233,8 @@
>                                 dac = spec->private_dac_nids[0];
>                                 badness += bad->shared_surr_main;
>                         } else if (!i)
> -                               badness += bad->no_primary_dac;
> +                               /* no additional badness for 0x15
(speaker) without DAC (during multi-io check) */
> +                               badness += pin == 0x15 ? 0 :
bad->no_primary_dac;
>                         else
>                                 badness += bad->no_dac;
>                 }

You cannot hardcode 0x15

if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
err = try_assign_dacs(codec, cfg->speaker_outs,
      cfg->speaker_pins,
      spec->multiout.extra_out_nid,
      spec->speaker_paths,
      spec->extra_out_badness);
if (err < 0)
return err;
badness += err;

Don't add err to badness when (err = 0x4000 && nid_has_volume(codec,
spec->multiout.dac_nid[0],HDA_OUTPUT) && cfg->lineout_type ==
AUTO_PIN_LINE_OUT && cfg->line_outs == 1 && cfg->hp_outs == 1 &&
cfg->speaker_outs == 1 && count_multiio_pins(codec, cfg->line_out_pins[0])
== 2 && number of analog dacs == 3)

>
> Now I'm getting the favored config:
>
> ==> lo_type=0, wired=1, mio=1, badness=0x352
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> hp_outs = 1b/0/0/0 : 2/0/0/0
> spk_outs = 15/0/0/0 : 3/0/0/0
> ==> lo_type=0, wired=1, mio=0, badness=0x120
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> hp_outs = 1b/0/0/0 : 4/0/0/0
> spk_outs = 15/0/0/0 : 3/0/0/0
> ==> lo_type=0, wired=0, mio=1, badness=0x112
> multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
> multi_ios(2) = 1a/18 : 3/4
> hp_outs = 1b/0/0/0 : 2/0/0/0
> spk_outs = 15/0/0/0 : 0/0/0/0
> ==> lo_type=0, wired=0, mio=0, badness=0x120
> multi_outs = 14/0/0/0 : 2/0/0/0 (type LO)
> hp_outs = 1b/0/0/0 : 3/0/0/0
> spk_outs = 15/0/0/0 : 0/0/0/0
> ==> restoring best_cfg
> ==> Best config: lo_type=0, wired=0, mio=1
> multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
> multi_ios(2) = 1a/18 : 3/4
> hp_outs = 1b/0/0/0 : 2/0/0/0
> spk_outs = 15/0/0/0 : 0/0/0/0

How do the driver know the volume control at node 0x02 is shared by hp,
line out and speaker when your spk_outs path not contain node 0x02

Since those Dell Inspirion 660 also is a 3stack desktop without speaker
with alc662  which need "Front+Headphone Playback Volume"

BTW do the driver need to disable independent headphone after your change ?
Independent headphone need line out and headphone use different DACs

Do alc662 support 4+2 or NOT ?

>
> > > The master volume control affects the line out volume (which is named
PCM,
> > > btw), but no other output. Muting the master, however, affects all
outputs.
> > >
> > > After changing to 4ch or 6ch, the PCM (line out) volume control acts
as a
> > > "master" for surround and center/lfe.
>
> > Seem "master playback volume" is not the correct name when using
surround
> > 5.1 and your config lost the virtual master playback volume
>
> It seems that this is fixable. Patch will follow.
>
> By the way, there is one thing I still don't understand. After booting
there
> is no "PCM Playback Volume" control in alsamixer. As soon as I've played
some
> wav file, it appears. Where does it come from, i.e. is it created by
kernel
> or alsa-lib/utils and why?
>

http://git.alsa-project.org/?p=alsa-lib.git;a=blob_plain;f=src/conf/cards/HDA-Intel.conf;hb=HEAD

It is a softvol plugin in HDA-Intel.conf which is needed for those alc660
codecs which have no hardware volume control

http://git.kernel.org/cgit/linux/kernel/git/tiwai/hda-emu.git/tree/codecs
Ingo Brueckl March 3, 2015, 3:24 p.m. UTC | #2
Raymond,

>> Now I'm getting the favored config:
>>
>> ==> Best config: lo_type=0, wired=0, mio=1
>> multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
>> multi_ios(2) = 1a/18 : 3/4
>> hp_outs = 1b/0/0/0 : 2/0/0/0
>> spk_outs = 15/0/0/0 : 0/0/0/0

> How do the driver know the volume control at node 0x02 is shared by hp,
> line out and speaker when your spk_outs path not contain node 0x02

It probably doesn't know. I suppose I'm losing the speaker (which isn't
connected nor used by me anyway).

On the other hand I'm getting a real Master as well as a Headphone switch,
Front, Surround, Center and LFE controls, and the channel mode. Everything's
working just great!

> BTW do the driver need to disable independent headphone after your
> change ?

I have only a headphone mute switch, no headphone volume control, if that's
what you mean. But since the master affects headphone volume, that's OK.

> Do alc662 support 4+2 or NOT ?

What do you mean exactly? I have 6 channel output.

>> By the way, there is one thing I still don't understand. [...]
>> "PCM Playback Volume" control in alsamixer.

> It is a softvol plugin in HDA-Intel.conf which is needed for those alc660
> codecs which have no hardware volume control

Thanks a lot. I'm understanding every single control now.

Ingo
Raymond Yau March 3, 2015, 4:17 p.m. UTC | #3
>
> >> Now I'm getting the favored config:
> >>
> >> ==> Best config: lo_type=0, wired=0, mio=1
> >> multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
> >> multi_ios(2) = 1a/18 : 3/4
> >> hp_outs = 1b/0/0/0 : 2/0/0/0
> >> spk_outs = 15/0/0/0 : 0/0/0/0
>
> > How do the driver know the volume control at node 0x02 is shared by hp,
> > line out and speaker when your spk_outs path not contain node 0x02
>
> It probably doesn't know. I suppose I'm losing the speaker (which isn't
> connected nor used by me anyway).

> >> multi_outs = 14/0/0/0 : 2/3/4/0 (type LO)
> >> multi_ios(2) = 1a/18 : 3/4
> >> hp_outs = 1b/0/0/0 : 2/0/0/0

path_has_mixer() does not imply shared volume

get_amp_nid_( path->ctls[NID_PATH_VOL_CTL] )  of two paths are same

if you just want Front+Headphone playback volume

>
> On the other hand I'm getting a real Master as well as a Headphone switch,
> Front, Surround, Center and LFE controls, and the channel mode.
Everything's
> working just great!
>
> > BTW do the driver need to disable independent headphone after your
> > change ?
>
> I have only a headphone mute switch, no headphone volume control, if
that's
> what you mean. But since the master affects headphone volume, that's OK.

As the original config only support stereo, pcm playback volume control
line out volume , headphone and speaker using different DAC 0x02 and 0x03

Try specify

spec->gen.indep_hp = 1;

before callin the auto parser in patch_alc662

Device: name="ALC662 rev3 Alt Analog", type="Audio", device=2

should appear in node 0x03 which has headphone playback volume

Codec: Realtek ALC662 rev3
Address: 0
AFG Function Id: 0x1 (unsol 1)
Vendor Id: 0x10ec0662
Subsystem Id: 0x8086204c
Revision Id: 0x100300
No Modem Function Group found
Default PCM:
    rates [0x5f0]: 32000 44100 48000 88200 96000 192000
    bits [0xe]: 16 20 24
    formats [0x1]: PCM
Default Amp-In caps: N/A
Default Amp-Out caps: N/A
State of AFG node 0x01:
  Power states:  D0 D1 D2 D3 CLKSTOP EPSS
  Power: setting=D0, actual=D0
GPIO: io=2, o=0, i=0, unsolicited=1, wake=0
  IO[0]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
  IO[1]: enable=0, dir=0, wake=0, sticky=0, data=0, unsol=0
Node 0x02 [Audio Output] wcaps 0x41d: Stereo Amp-Out
  Control: name="PCM Playback Volume", index=0, device=0
    ControlAmp: chs=3, dir=Out, idx=0, ofs=0
  Device: name="ALC662 rev3 Analog", type="Audio", device=0
  Amp-Out caps: ofs=0x57, nsteps=0x57, stepsize=0x02, mute=0
  Amp-Out vals:  [0x57 0x57]
  Converter: stream=0, channel=0
  PCM:
    rates [0x560]: 44100 48000 96000 192000
    bits [0xe]: 16 20 24
    formats [0x1]: PCM
  Power states:  D0 D1 D2 D3 EPSS
  Power: setting=D0, actual=D0
Node 0x03 [Audio Output] wcaps 0x41d: Stereo Amp-Out
  Control: name="Speaker Playback Volume", index=0, device=0
    ControlAmp: chs=3, dir=Out, idx=0, ofs=0
  Amp-Out caps: ofs=0x57, nsteps=0x57, stepsize=0x02, mute=0
  Amp-Out vals:  [0x57 0x57]
  Converter: stream=0, channel=0
  PCM:
    rates [0x560]: 44100 48000 96000 192000
    bits [0xe]: 16 20 24
    formats [0x1]: PCM
  Power states:  D0 D1 D2 D3 EPSS
  Power: setting=D0, actual=D0
Node 0x04 [Audio Output] wcaps 0x41d: Stereo Amp-Out
  Control: name="Headphone Playback Volume", index=0, device=0
    ControlAmp: chs=3, dir=Out, idx=0, ofs=0
  Amp-Out caps: ofs=0x57, nsteps=0x57, stepsize=0x02, mute=0
  Amp-Out vals:  [0x57 0x57]
  Converter: stream=0, channel=0
  PCM:
    rates [0x560]: 44100 48000 96000 192000
    bits [0xe]: 16 20 24
    formats [0x1]: PCM
  Power states:  D0 D1 D2 D3 EPSS
  Power: setting=D0, actual=D0
diff mbox

Patch

diff -Nur a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
--- a/sound/pci/hda/hda_generic.c	2015-02-11 08:01:12.000000000 +0100
+++ b/sound/pci/hda/hda_generic.c	2015-03-02 22:57:34.799192329 +0100
@@ -1233,7 +1233,8 @@ 
 				dac = spec->private_dac_nids[0];
 				badness += bad->shared_surr_main;
 			} else if (!i)
-				badness += bad->no_primary_dac;
+				/* no additional badness for 0x15 (speaker) without DAC (during multi-io check) */
+				badness += pin == 0x15 ? 0 : bad->no_primary_dac;
 			else
 				badness += bad->no_dac;
 		}