All of lore.kernel.org
 help / color / mirror / Atom feed
* Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
@ 2010-10-30 10:24 Christian Wisner-Carlson
  2010-11-01 15:59 ` Clemens Ladisch
  0 siblings, 1 reply; 7+ messages in thread
From: Christian Wisner-Carlson @ 2010-10-30 10:24 UTC (permalink / raw)
  To: alsa-devel

This patch adds a mixer switch for soundcards using the snd-virtuoso
driver and pcm1796/pcm1792(a) DAC(s) which switches between Stereo,
Balanced Left, and Balanced Right output modes.

The PCM179x series has a "Monaural Mode" that outputs a single channel
in differential (and therefore balanced, because of the buffer
circuit) mode, which boosts the SNR and allows for common mode
rejection (with the proper cable). Simply use the left output as the
noninverting signal and the right output as the inverting output. The
datasheets for both the pcm1792a and pcm1796 provide application
suggestions, which boil down mainly to "connect an XLR jack to the
outputs of the normal application circuit".

I tested this thoroughly with an Asus Xonar Essence ST, although it
should also work with the HDAV, Essence STX, and probably other cards.
I get no noticeable interference when running balanced audio from the
card over approximately 150ft of unshielded twisted pair cable which I
have running through my walls.

The driver defaults to stereo output and this patch will not cause
issues for users who do not need/want this feature. The patches that I
am posting only give one control regardless of whether or not more
than one DAC is connected. I have another patchset that gives
individual control of all 4 dacs in the Xonar Essence ST+H6 and
HDAV+H6 setups (H6 is an optional daughterboard for surround sound).
It allows for 4 balanced outputs, 8 unbalanced outputs, or any
combination of balanced and unbalanced outputs. HOWEVER, it adds 4
mixer controls and the code isn't very pretty. If people want it, I'll
post it as well and/or take suggestions on how to improve it.

Here is a diff of xonar_pcm179x.c, which is the only changed file. The
diff is against alsa-driver 1.0.23 but should cleanly patch the GIT
revision. Please tell me if this is not the correct way to post a
patch, and tell me if it seems like a candidate to be merged.

Christian Wisner-Carlson

--- ./alsa-driver-1.0.23/alsa-kernel/pci/oxygen/xonar_pcm179x.c	2010-04-16
07:10:10.000000000 -0400
+++ ./anothermono/alsa-driver-1.0.23/alsa-kernel/pci/oxygen/xonar_pcm179x.c	2010-10-30
05:28:55.000000000 -0400
@@ -176,6 +176,8 @@
 	unsigned int current_rate;
 	bool os_128;
 	bool hp_active;
+	bool monomode;
+	bool rightmono;
 	s8 hp_gain_offset;
 	bool has_cs2000;
 	u8 cs2000_fun_cfg_1;
@@ -532,6 +534,13 @@
 		reg = PCM1796_OS_64;
 	else
 		reg = PCM1796_OS_32;
+	
+	if (data->monomode)
+	        reg = reg | PCM1796_MONO;
+	
+	if (data->rightmono)
+	        reg = reg | PCM1796_CHSL_RIGHT;
+	
 	for (i = 0; i < data->dacs; ++i)
 		pcm1796_write_cached(chip, i, 20, reg);
 }
@@ -719,6 +728,19 @@
 	return 0;
 }

+static int monomode_info(struct snd_kcontrol *ctl, struct
snd_ctl_elem_info *info)
+{
+	static const char *const names[3] = { "Stereo", "Balanced Left",
"Balanced Right" };
+
+	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	info->count = 1;
+	info->value.enumerated.items = 3;
+	if (info->value.enumerated.item >= 3)
+		info->value.enumerated.item = 0;
+	strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
+	return 0;
+}
+
 static int os_128_get(struct snd_kcontrol *ctl,
 		      struct snd_ctl_elem_value *value)
 {
@@ -729,6 +751,18 @@
 	return 0;
 }

+static int monomode_get(struct snd_kcontrol *ctl,
+		      struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	struct xonar_pcm179x *data = chip->model_data;
+	int newvalue;
+	newvalue = data->monomode + (data->monomode & data->rightmono);
+
+	value->value.enumerated.item[0] = newvalue;
+	return 0;
+}
+
 static int os_128_put(struct snd_kcontrol *ctl,
 		      struct snd_ctl_elem_value *value)
 {
@@ -751,6 +785,25 @@
 	return changed;
 }

+static int monomode_put(struct snd_kcontrol *ctl,
+		      struct snd_ctl_elem_value *value)
+{
+	struct oxygen *chip = ctl->private_data;
+	struct xonar_pcm179x *data = chip->model_data;
+	int changed;
+
+	mutex_lock(&chip->mutex);
+	changed = value->value.enumerated.item[0] !=
+	   (data->monomode + (data->monomode & data->rightmono));
+	if (changed) {
+		data->monomode = (value->value.enumerated.item[0]) ? 1 : 0;
+		data->rightmono = (value->value.enumerated.item[0] == 2) ? 1 : 0;
+		update_pcm1796_oversampling(chip);
+	}
+	mutex_unlock(&chip->mutex);
+	return changed;
+}
+
 static const struct snd_kcontrol_new os_128_control = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "DAC Oversampling Playback Enum",
@@ -759,6 +812,14 @@
 	.put = os_128_put,
 };

+static const struct snd_kcontrol_new monomode_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "DAC Mono Mode Playback Enum",
+	.info = monomode_info,
+	.get = monomode_get,
+	.put = monomode_put,
+};
+
 static int st_output_switch_info(struct snd_kcontrol *ctl,
 				 struct snd_ctl_elem_info *info)
 {
@@ -932,6 +993,9 @@
 	err = snd_ctl_add(chip->card, snd_ctl_new1(&os_128_control, chip));
 	if (err < 0)
 		return err;
+	err = snd_ctl_add(chip->card, snd_ctl_new1(&monomode_control, chip));
+	if (err < 0)
+		return err;
 	return 0;
 }




I am also in the process of adding a Phase Invert switch and
(possibly) Deemphasis control for the PCM179x DACs as well, and will
post patches if anyone is interested.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
  2010-10-30 10:24 Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs) Christian Wisner-Carlson
@ 2010-11-01 15:59 ` Clemens Ladisch
  2010-11-01 17:02   ` Christian Wisner-Carlson
  2010-11-03  4:50   ` Christian Wisner-Carlson
  0 siblings, 2 replies; 7+ messages in thread
From: Clemens Ladisch @ 2010-11-01 15:59 UTC (permalink / raw)
  To: Christian Wisner-Carlson; +Cc: alsa-devel

Christian Wisner-Carlson wrote:
> I tested this thoroughly with an Asus Xonar Essence ST, although it
> should also work with the HDAV, Essence STX, and probably other cards.

D2/D2X, Xense.

> The patches that I am posting only give one control regardless of
> whether or not more than one DAC is connected. I have another patchset
> that gives individual control of all 4 dacs in the Xonar Essence ST+H6
> and HDAV+H6 setups (H6 is an optional daughterboard for surround sound).

BTW: any new information about the H6 problem?

> It allows for 4 balanced outputs, 8 unbalanced outputs, or any
> combination of balanced and unbalanced outputs. HOWEVER, it adds 4
> mixer controls and the code isn't very pretty.

The controller can route any stereo pair to each DAC, so it would be a
good idea to have one global control that also affects this routing so
that, e.g., configuring the card for 4 outputs works correctly when
playing 4-channel data.

Alternatively, having low-level controls for each detail of the hardware
is workable when somebody (i.e., you :-) writes a special graphical tool
to configure the Xonar outputs (any the other settings).

The Xense has one PCM1796 for the front channels and a CS4362A for the
other channels.  Like the stereo-only cards, this would result in an odd
number of channels in balanced mode, which is somewhat counterintuitive
because the controller would need to be fed an extra unused channel.

> Please tell me if this is not the correct way to post a patch, and
> tell me if it seems like a candidate to be merged.

Your mailer wrapped lines; see Documentation/email-clients.txt.
Also see Documentation/SubmittingPatches.

Overall, this patch looks good.  But I wouldn't want to apply it without
the followup patch that handles the D2's four DACs.

> @@ -532,6 +534,13 @@
>  		reg = PCM1796_OS_64;
>  	else
>  		reg = PCM1796_OS_32;
> +	
> +	if (data->monomode)
> +	        reg = reg | PCM1796_MONO;
> +	
> +	if (data->rightmono)
> +	        reg = reg | PCM1796_CHSL_RIGHT;
> +	
>  	for (i = 0; i < data->dacs; ++i)
>  		pcm1796_write_cached(chip, i, 20, reg);
>  }

This function's purpose is no longer to _only_ update the oversampling
setting; please rename it to, e.g., update_reg20.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
  2010-11-01 15:59 ` Clemens Ladisch
@ 2010-11-01 17:02   ` Christian Wisner-Carlson
  2010-11-02  8:56     ` Clemens Ladisch
  2010-11-03  4:50   ` Christian Wisner-Carlson
  1 sibling, 1 reply; 7+ messages in thread
From: Christian Wisner-Carlson @ 2010-11-01 17:02 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

I have the  H6 working somewhat. I added a lot of I2C resets (and a
loop to make sure the bus is free before trying to write to it).
HOWEVER, when the H6 is connected, and i switch from 128x OS, the
sound stops and becomes a high pitched whine or other noise, or just
stops, as if the DACs lost lock on the MCLK signal. The same thing
happens when i play ANYTHING at 96khz or 192khz sampling rate.
However, 88.2khz still plays at 64x OS. Given that a 24.576MHz
single-ended signalis being sent UNBUFFERED over an UNSHIELDED  ribbon
cable, this does not surprise me. I am guessing that the Asus drivers
probably use a lower MCLK rate. Any ideas? My old Audigy 2 buffered
the MCLK (24.576Mhz) with a 74F125, although I am reluctant to do
this. Perhaps I will try replacing the relevent part of the ribbon
cable with a shielded cable. Is this worth trying?

Christian Wisner-Carlson

On Mon, Nov 1, 2010 at 11:59 AM, Clemens Ladisch <clemens@ladisch.de> wrote:
> Christian Wisner-Carlson wrote:
>> I tested this thoroughly with an Asus Xonar Essence ST, although it
>> should also work with the HDAV, Essence STX, and probably other cards.
>
> D2/D2X, Xense.
>
>> The patches that I am posting only give one control regardless of
>> whether or not more than one DAC is connected. I have another patchset
>> that gives individual control of all 4 dacs in the Xonar Essence ST+H6
>> and HDAV+H6 setups (H6 is an optional daughterboard for surround sound).
>
> BTW: any new information about the H6 problem?
>
>> It allows for 4 balanced outputs, 8 unbalanced outputs, or any
>> combination of balanced and unbalanced outputs. HOWEVER, it adds 4
>> mixer controls and the code isn't very pretty.
>
> The controller can route any stereo pair to each DAC, so it would be a
> good idea to have one global control that also affects this routing so
> that, e.g., configuring the card for 4 outputs works correctly when
> playing 4-channel data.
>
> Alternatively, having low-level controls for each detail of the hardware
> is workable when somebody (i.e., you :-) writes a special graphical tool
> to configure the Xonar outputs (any the other settings).
>
> The Xense has one PCM1796 for the front channels and a CS4362A for the
> other channels.  Like the stereo-only cards, this would result in an odd
> number of channels in balanced mode, which is somewhat counterintuitive
> because the controller would need to be fed an extra unused channel.
>
>> Please tell me if this is not the correct way to post a patch, and
>> tell me if it seems like a candidate to be merged.
>
> Your mailer wrapped lines; see Documentation/email-clients.txt.
> Also see Documentation/SubmittingPatches.
>
> Overall, this patch looks good.  But I wouldn't want to apply it without
> the followup patch that handles the D2's four DACs.
>
>> @@ -532,6 +534,13 @@
>>               reg = PCM1796_OS_64;
>>       else
>>               reg = PCM1796_OS_32;
>> +
>> +     if (data->monomode)
>> +             reg = reg | PCM1796_MONO;
>> +
>> +     if (data->rightmono)
>> +             reg = reg | PCM1796_CHSL_RIGHT;
>> +
>>       for (i = 0; i < data->dacs; ++i)
>>               pcm1796_write_cached(chip, i, 20, reg);
>>  }
>
> This function's purpose is no longer to _only_ update the oversampling
> setting; please rename it to, e.g., update_reg20.
>
>
> Regards,
> Clemens
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
  2010-11-01 17:02   ` Christian Wisner-Carlson
@ 2010-11-02  8:56     ` Clemens Ladisch
  0 siblings, 0 replies; 7+ messages in thread
From: Clemens Ladisch @ 2010-11-02  8:56 UTC (permalink / raw)
  To: Christian Wisner-Carlson; +Cc: alsa-devel

Christian Wisner-Carlson wrote:
> I have the  H6 working somewhat. I added a lot of I2C resets (and a
> loop to make sure the bus is free before trying to write to it).

Can you find out when exactly the I²C bus gets wedged?  (I'd guess at
the first access to an off-board DAC.)

Do any of the I²C writes to the H6 actually get through (i.e., do
all eight volume controls work?)

(The first D2 Windows driver versions had a bug, taken over from the
AK4396 models, where it used the wrong SPI output for the fourth DAC,
so that that chip would never get any register write.  Nobody noticed.)

> HOWEVER, when the H6 is connected, and i switch from 128x OS,

"to"?

> the sound stops and becomes a high pitched whine or other noise, or
> just stops, as if the DACs lost lock on the MCLK signal. The same
> thing happens when i play ANYTHING at 96khz or 192khz sampling rate.
> However, 88.2khz still plays at 64x OS. Given that a 24.576MHz
> single-ended signalis being sent UNBUFFERED over an UNSHIELDED  ribbon
> cable, this does not surprise me. I am guessing that the Asus drivers
> probably use a lower MCLK rate. Any ideas?

As far as I can tell (without running the Windows driver), it uses the
standard 256x/128x MCLK rates for the standard I²S output, but the
CS2000 (connected to the "ADC1" I²S MCLK) is always configured for half
that rate although the PCM179x registers are still configured for the
'full' rate.

Can you find out which of the I²S MCLK outputs is used for the onboard
DAC and for the H6?  I'd conclude from the above that the CS2000 might
be used for all of them, but then I don't know how the HDAV would work
with the H6 at high clock rates.

Does the Windows driver allow 192 kHz with the H6?  (This is using 128x
in both drivers.)

> My old Audigy 2 buffered the MCLK (24.576Mhz) with a 74F125, although
> I am reluctant to do this. Perhaps I will try replacing the relevent
> part of the ribbon cable with a shielded cable. Is this worth trying?

Better try changing mclk_from_rate() to always use the smallest possible
MCLK rate; update_pcm1796_oversampling() then needs to be changed too.
According to the PCM179x datasheets, up to 48 kHz requires at least
256x, while 96-192 kHz can run at 128x.  (We always use I²C fast mode,
even with codecs that are not documented to support it; the CMI8788
seems to be buggy at the standard I²C speed.)


Regards,
Clemens
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
  2010-11-01 15:59 ` Clemens Ladisch
  2010-11-01 17:02   ` Christian Wisner-Carlson
@ 2010-11-03  4:50   ` Christian Wisner-Carlson
  2010-11-03 13:01     ` Christian Wisner-Carlson
  2010-11-05 13:17     ` Clemens Ladisch
  1 sibling, 2 replies; 7+ messages in thread
From: Christian Wisner-Carlson @ 2010-11-03  4:50 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

>> It allows for 4 balanced outputs, 8 unbalanced outputs, or any
>> combination of balanced and unbalanced outputs. HOWEVER, it adds 4
>> mixer controls and the code isn't very pretty.
>
> The controller can route any stereo pair to each DAC, so it would be a
> good idea to have one global control that also affects this routing so
> that, e.g., configuring the card for 4 outputs works correctly when
> playing 4-channel data.

Currently, routing is set up by void oxygen_update_dac_routing(struct
oxygen *chip) in oxygen_mixer.c.
However,  it only allows for five different routing configurations,
which it statically defines internally as int reg_values[5].
Do you mind (ie, would you mind merging/using it) if I defined a new struct:
struct oxygen_routing_table = {
	u8 channels;
	unsigned int dac0;
	unsigned int dac1;
	unsigned int dac2;
	unsigned int dac3;
}
that would be passed to oxygen_update_dac_routing() as a new field of
struct oxygen? This would allow for
arbitrary routing configurations for the dacs (needed to implement 4
channel balanced output) and would
not require many changes to the driver as a whole. Where should I
define this struct? (ie, in what file?)

Thanks,
Christian Wisner-Carlson

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
  2010-11-03  4:50   ` Christian Wisner-Carlson
@ 2010-11-03 13:01     ` Christian Wisner-Carlson
  2010-11-05 13:17     ` Clemens Ladisch
  1 sibling, 0 replies; 7+ messages in thread
From: Christian Wisner-Carlson @ 2010-11-03 13:01 UTC (permalink / raw)
  To: Clemens Ladisch; +Cc: alsa-devel

I realize that this is not completely necessary, but it really would
get rid of a lot of potential duplicate code and could allow some
current code to be simplified.

On Wed, Nov 3, 2010 at 12:50 AM, Christian Wisner-Carlson
<christian@freedomofknowledge.org> wrote:
>>> It allows for 4 balanced outputs, 8 unbalanced outputs, or any
>>> combination of balanced and unbalanced outputs. HOWEVER, it adds 4
>>> mixer controls and the code isn't very pretty.
>>
>> The controller can route any stereo pair to each DAC, so it would be a
>> good idea to have one global control that also affects this routing so
>> that, e.g., configuring the card for 4 outputs works correctly when
>> playing 4-channel data.
>
> Currently, routing is set up by void oxygen_update_dac_routing(struct
> oxygen *chip) in oxygen_mixer.c.
> However,  it only allows for five different routing configurations,
> which it statically defines internally as int reg_values[5].
> Do you mind (ie, would you mind merging/using it) if I defined a new struct:
> struct oxygen_routing_table = {
>        u8 channels;
>        unsigned int dac0;
>        unsigned int dac1;
>        unsigned int dac2;
>        unsigned int dac3;
> }
> that would be passed to oxygen_update_dac_routing() as a new field of
> struct oxygen? This would allow for
> arbitrary routing configurations for the dacs (needed to implement 4
> channel balanced output) and would
> not require many changes to the driver as a whole. Where should I
> define this struct? (ie, in what file?)
>
> Thanks,
> Christian Wisner-Carlson
>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs)
  2010-11-03  4:50   ` Christian Wisner-Carlson
  2010-11-03 13:01     ` Christian Wisner-Carlson
@ 2010-11-05 13:17     ` Clemens Ladisch
  1 sibling, 0 replies; 7+ messages in thread
From: Clemens Ladisch @ 2010-11-05 13:17 UTC (permalink / raw)
  To: Christian Wisner-Carlson; +Cc: alsa-devel

Christian Wisner-Carlson wrote:
>>> It allows for 4 balanced outputs, 8 unbalanced outputs, or any
>>> combination of balanced and unbalanced outputs. HOWEVER, it adds 4
>>> mixer controls and the code isn't very pretty.
>>
>> The controller can route any stereo pair to each DAC, so it would be a
>> good idea to have one global control that also affects this routing so
>> that, e.g., configuring the card for 4 outputs works correctly when
>> playing 4-channel data.
> 
> Currently, routing is set up by void oxygen_update_dac_routing(struct
> oxygen *chip) in oxygen_mixer.c.
> However,  it only allows for five different routing configurations,
> which it statically defines internally as int reg_values[5].
> Do you mind (ie, would you mind merging/using it) if I defined a new struct:
> struct oxygen_routing_table = {
> 	u8 channels;
> 	unsigned int dac0;
> 	unsigned int dac1;
> 	unsigned int dac2;
> 	unsigned int dac3;
> }
> that would be passed to oxygen_update_dac_routing() as a new field of
> struct oxygen? This would allow for
> arbitrary routing configurations for the dacs (needed to implement 4
> channel balanced output) and would
> not require many changes to the driver as a whole.

This would move the responsibility for the actual routing decisions from
this function into its callers.  However, both the stereo-upmixing and
the balanced-output controls affect the routing, so some code has to
handle the interdependencies.  At the moment, this function sets the
routing depending on the current channel count and the upmixing setting;
I think that the balanced-output setting is just a third such parameter.

Anyway, I'm just concerned about how the controls looks to the user, not
so much about its implementation, which can be changed later (if I
wanted to, and if I had the time).

I'd be happy to merge any code that handles four DACs.  Separate
controls for each DAC are OK too if, eventually, there are additional
controls for the routing, and if there is a userspace tool to manage
these settings together.

> Where should I define this struct? (ie, in what file?)

As an interface between the core driver and module-specific drivers,
oxygen.h.


Regards,
Clemens

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-11-05 13:15 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-30 10:24 Balanced output support for Xonar: Patches for Virtuoso driver to add mixer option for balanced mono output (PCM179x dacs) Christian Wisner-Carlson
2010-11-01 15:59 ` Clemens Ladisch
2010-11-01 17:02   ` Christian Wisner-Carlson
2010-11-02  8:56     ` Clemens Ladisch
2010-11-03  4:50   ` Christian Wisner-Carlson
2010-11-03 13:01     ` Christian Wisner-Carlson
2010-11-05 13:17     ` Clemens Ladisch

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.