All of lore.kernel.org
 help / color / mirror / Atom feed
* Why analog loopback of sigmatel devices got removed?
@ 2009-06-18 23:50 Maxim Levitsky
  2009-06-19  6:32 ` Takashi Iwai
  0 siblings, 1 reply; 14+ messages in thread
From: Maxim Levitsky @ 2009-06-18 23:50 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 769 bytes --]

Hi,

Due to lack of time, I didn't update kernel on my desktop system.
Now I notice that analog loopback go removed. Why?


Searching around I found this:

http://article.gmane.org/gmane.linux.alsa.devel/59878

* Removed analog loopback mixer items, not mentioned in sigmatel
datasheets and
  reported to break sound support.


First they are mention. It took me lot of time to find them.
I only have added the loopback items for devices that have this feature in datasheet.

Then how it can break sound support? could you explain?
I need this feature since I use it with my TV card, and I know more users that use that feature.


I don't know about other devices, but I attach the my patch that was included in kernel for this feature.


Best regards,
	Maxim Levitsky

[-- Attachment #2: 0004-add-support-for-analog-loopback-to-STAC9204-9205-922.patch --]
[-- Type: text/x-patch, Size: 3941 bytes --]

>From ea1a7a5a8113f8c39db8391226adbbe383f03355 Mon Sep 17 00:00:00 2001
From: Maxim Levitsky <maximlevitsky@gmail.com>
Date: Mon, 3 Sep 2007 14:18:17 +0300
Subject: [PATCH] add support for analog loopback to STAC9204/9205/922x/927x

The analog loopback routes the sound just before it enters ADC0 to output of DAC0

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
 pci/hda/patch_sigmatel.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/pci/hda/patch_sigmatel.c b/pci/hda/patch_sigmatel.c
index 297f740..c94775c 100644
--- a/pci/hda/patch_sigmatel.c
+++ b/pci/hda/patch_sigmatel.c
@@ -147,6 +147,7 @@ struct sigmatel_spec {
 	/* i/o switches */
 	unsigned int io_switch[2];
 	unsigned int clfe_swap;
+	unsigned int aloopback;
 
 	struct hda_pcm pcm_rec[2];	/* PCM information */
 
@@ -296,6 +297,49 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 				     spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
 }
 
+#define stac92xx_aloopback_info snd_ctl_boolean_mono_info
+
+static int stac92xx_aloopback_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+
+	ucontrol->value.integer.value[0] = spec->aloopback;
+	return 0;
+}
+
+static int stac92xx_aloopback_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+	unsigned int dac_mode;
+
+	if (spec->aloopback == ucontrol->value.integer.value[0])
+		return 0;
+
+	spec->aloopback = ucontrol->value.integer.value[0];
+
+
+	dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
+		kcontrol->private_value & 0xFFFF, 0x0);
+
+	if (spec->aloopback) {
+		snd_hda_power_up(codec);
+		dac_mode |= 0x40;
+	} else {
+		snd_hda_power_down(codec);
+		dac_mode &= ~0x40;
+	}
+
+	snd_hda_codec_write_cache(codec, codec->afg, 0,
+		kcontrol->private_value >> 16, dac_mode);
+
+	return 1;
+}
+
+
 static struct hda_verb stac9200_core_init[] = {
 	/* set dac0mux for dac converter */
 	{ 0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
@@ -346,6 +390,17 @@ static struct hda_verb stac9205_core_init[] = {
 		.put = stac92xx_mux_enum_put, \
 	}
 
+#define STAC_ANALOG_LOOPBACK(verb_read,verb_write) \
+	{ \
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name  = "Analog Loopback", \
+		.count = 1, \
+		.info  = stac92xx_aloopback_info, \
+		.get   = stac92xx_aloopback_get, \
+		.put   = stac92xx_aloopback_put, \
+		.private_value = verb_read | (verb_write << 16), \
+	}
+
 
 static struct snd_kcontrol_new stac9200_mixer[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
@@ -377,6 +432,7 @@ static struct snd_kcontrol_new stac922x_mixer[] = {
 /* This needs to be generated dynamically based on sequence */
 static struct snd_kcontrol_new stac9227_mixer[] = {
 	STAC_INPUT_SOURCE,
+	STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB),
 	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
 	{ } /* end */
@@ -384,6 +440,7 @@ static struct snd_kcontrol_new stac9227_mixer[] = {
 
 static struct snd_kcontrol_new stac927x_mixer[] = {
 	STAC_INPUT_SOURCE,
+	STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB),
 	HDA_CODEC_VOLUME("InMux Capture Volume", 0x15, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("InVol Capture Volume", 0x18, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1b, 0x0, HDA_OUTPUT),
@@ -400,6 +457,7 @@ static struct snd_kcontrol_new stac9205_mixer[] = {
 		.put = stac92xx_dmux_enum_put,
 	},
 	STAC_INPUT_SOURCE,
+	STAC_ANALOG_LOOPBACK(0xFE0, 0x7E0),
 	HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT),
-- 
1.5.2.3


[-- Attachment #3: Type: text/plain, Size: 160 bytes --]

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

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-18 23:50 Why analog loopback of sigmatel devices got removed? Maxim Levitsky
@ 2009-06-19  6:32 ` Takashi Iwai
  2009-06-19  7:27   ` segfault when setting swparams! help Guilherme
                     ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Takashi Iwai @ 2009-06-19  6:32 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: alsa-devel

At Fri, 19 Jun 2009 02:50:35 +0300,
Maxim Levitsky wrote:
> 
> Hi,
> 
> Due to lack of time, I didn't update kernel on my desktop system.
> Now I notice that analog loopback go removed. Why?

Because it harms than helps more often.  I've got tons of bug reports
and been upset just because users blindly set "Analog Loopback" mixer
switch and lost their sound output.  This is no mixer element that
behaves intuitively -- it shuts out PCM output instead of adding the
analog loopback like other hardwares.

The feature is still available, though.  You just need to give the
driver an instruction via sysfs.  Namely, write to sysfs files
corresponding to the IDT codec like
	# echo "loopback yes" > /sys/class/sound/hwC0D0/hints
	# echo 1 > /sys/class/sound/hwC0D0/reconfig
Then the driver will reconfigure with the loopback mixer element.
	
I have a patch series to add this with a "patch" firmware file to
make it easier, which I'm going to send an RFC to this ML soon later.
Take a look at topic/hda-patch branch on sound-unstable tree.


thanks,

Takashi

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

* segfault when setting swparams! help
  2009-06-19  6:32 ` Takashi Iwai
@ 2009-06-19  7:27   ` Guilherme
  2009-06-19  7:31     ` Takashi Iwai
  2009-06-19  8:21   ` Why analog loopback of sigmatel devices got removed? Maxim Levitsky
  2009-06-19 18:18   ` Maxim Levitsky
  2 siblings, 1 reply; 14+ messages in thread
From: Guilherme @ 2009-06-19  7:27 UTC (permalink / raw)
  To: alsa-devel

Mates...

I am getting a segfault when running my app:

This is the part of the code where I am getting the error:

            if ((err = set_swparams(handle, swparams)) < 0) {
                  printf("Setting of swparams failed: %s\n", 
snd_strerror(err));
                  exit(EXIT_FAILURE);
           }

That is the gdb output:  (*The full program code's been posted below the 
debug output)

Starting program: /home/guilherme/Experimentos/PCM
[Thread debugging using libthread_db enabled]
[New Thread 0xb7c896c0 (LWP 3391)]
[Switching to Thread 0xb7c896c0 (LWP 3391)]

Breakpoint 1, main (argc=1, argv=0xbfa27da4) at pcm.c:777
777                    };
(gdb) n
783                    int method = 0;
(gdb) n
791                    morehelp = 0;
(gdb) n
794                                if ((c = getopt_long(argc, argv, 
"hd:r:c:f:b:p:m:o:vne", long_option, NULL)) < 0)
(gdb) nn
Undefined command: "nn".  Try "help".
(gdb) n
857                  if(morehelp) {
(gdb) n
863                    err = snd_output_stdio_attach(&output, &stdout, 0);
(gdb) n
864                    if (err < 0) {
(gdb) n
869                    printf("Playback device is %s\n", device);
(gdb) n
Playback device is default
870                    printf("Stream parameters are %iHz, %s, %i 
channels\n", rate, snd_pcm_format_name(format), channels);
(gdb) n
Stream parameters are 48000Hz, S16_LE, 1 channels
871                    printf("sine wave rate is %i %.4fHz\n", freq);
(gdb) n
sine wave rate is 0 0.0000Hz
872                    printf("Using transfer method: %s\n", 
transfer_methods[method].name);
(gdb) n
Using transfer method: write
874                    if ((err = snd_pcm_open(&handle, device, 
SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
(gdb) n
879                    if ((err = set_hwparams(handle, hwparams, 
transfer_methods[method].access)) < 0) {
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0xb7d47e3f in memset () from /lib/libc.so.6
(gdb) Quit
(gdb) quit
The program is running.  Exit anyway? (y or n)





That  is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include <alsa/asoundlib.h>
#include <sys/time.h>
#include <math.h>

static char *device = "default";                       //playback device 
aplay -l
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;   //sample format 
unsigned 16 bit endian
static unsigned int rate = 48000;                      //stream rate
static unsigned int channels = 1;                       //contagem dos 
canais
static unsigned int buffer_time = 500;              //ring buffer length 
on us
static unsigned int period_time = 100;              //period time in us
static double freq = 440;                              // frequencia da 
senóide em Hz
static int verbose = 0;                                //verbose flag
static int resample = 1;                               //abilitar 
alsa-lib resampling
static int period_event = 0;                           // produz um 
event pool a cada periodo

static snd_pcm_sframes_t buffer_size;                  //quantidade de 
buffers frames
static snd_pcm_sframes_t period_size;                  //quantidade de 
periods frames
static snd_output_t *output = NULL;                    //ALSA usa esse 
ponteiro para lidar com output objects


static void generate_sine(const snd_pcm_channel_area_t *areas,
                                          snd_pcm_uframes_t offset,
                                          int count, double *_phase)
{
        static double max_phase = 2. * M_PI;
        double phase = *_phase;
        double step = max_phase*freq / (double)rate;
        double res;
        unsigned char *samples[channels], *tmp;
        int steps[channels];
        unsigned int chn, byte;
       
        union {
                int i;
                unsigned char c[4];
        } ires;
        unsigned int maxval = (1 << (snd_pcm_format_width(format) - 1)) - 1;
        int bps = snd_pcm_format_width(format) / 8; //bits per sample
       
        /*verificar e preparar o conteúdo das areas*/
        for (chn = 0; chn < channels; chn++) {
            if ((areas[chn].first % 8) != 0) {
                    printf("areas[%i].first == %i, abortando...\n", chn, 
areas[chn].first);
                    exit(EXIT_FAILURE);
            }
            //pega endereço e offset da area
            samples[chn] = /*(signed short *)*/(((unsigned char 
*)areas[chn].addr) + (areas[chn].first / 8));
           
         if ((areas[chn].step % 16) != 0) {
                printf("areas[%i].step == %i, aborting...\n", chn, 
areas[chn].step);
                exit(EXIT_FAILURE);
         }
           
                steps[chn] = areas[chn].step / 8;
                samples[chn] += offset * steps[chn];
        }
       
        //completa os channels da area
        while(count-- > 0) {
            res = sin(phase) * maxval;
            ires.i = res;
            tmp = ires.c;
            for (chn = 0; chn < channels; chn++) {
                    for (byte = 0; byte < (unsigned int)bps; byte++) 
*(samples[chn] + byte) = tmp[byte];
                        samples[chn] += steps[chn];
                    }
                    phase += step;
                    if (phase >= max_phase)
                            phase -= max_phase;
                    }
                    *_phase = phase;
  
}                               


static int set_hwparams(snd_pcm_t *handle,
                                snd_pcm_hw_params_t *params,
                                snd_pcm_access_t access)
{
        unsigned int rrate;
        snd_pcm_uframes_t size;
        int err, dir;
       
        /*escolha todos os parametros*/
        err = snd_pcm_hw_params_any(handle, params);
        if (err < 0) {
                printf("Broken configuration for playback: no 
configuration available: %s\n", snd_strerror(err));
                return err;
        }
       
        /*set hardware resampling*/
        err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
        if (err < 0) {
                printf("Resampling setup failed for playback: %s\n", 
snd_strerror(err));
                return err;
        }
       
      /* set the interleaved read/write format */
      err = snd_pcm_hw_params_set_access(handle, params, access);
      if (err < 0) {
            printf("Access type not available for playback: %s\n", 
snd_strerror(err));
            return err;
       }
      
      /* set the sample format SND_PCM_FORMAT_S16 */
       err = snd_pcm_hw_params_set_format(handle, params, format);
       if (err < 0) {
             printf("Sample format not available for playback: %s\n", 
snd_strerror(err));
             return err;
      }
     
        /* set the count of channels 1  */
       err = snd_pcm_hw_params_set_channels(handle, params, channels);
       if (err < 0) {
             printf("Channels count (%i) not available for playbacks: 
%s\n", channels, snd_strerror(err));
             return err;
      }
     
      /* set the stream rate */
       rrate = rate;
       err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
       if (err < 0) {
             printf("Rate %iHz not available for playback: %s\n", rate, 
snd_strerror(err));
             return err;
      }
      if (rrate != rate) {
             printf("Rate doesn't match (requested %iHz, get %iHz)\n", 
rate, err);
            return -EINVAL;
      }
      /* set the buffer time */
      err = snd_pcm_hw_params_set_buffer_time_near(handle, params, 
&buffer_time, &dir);
      if (err < 0) {
           printf("Unable to set buffer time %i for playback: %s\n", 
buffer_time, snd_strerror(err));
           return err;
      }
      err = snd_pcm_hw_params_get_buffer_size(params, &size);
      if (err < 0) {
           printf("Unable to get buffer size for playback: %s\n", 
snd_strerror(err));
           return err;
      }
      buffer_size = size;
      /* set the period time */
      err = snd_pcm_hw_params_set_period_time_near(handle, params, 
&period_time, &dir);
      if (err < 0) {
           printf("Unable to set period time %i for playback: %s\n", 
period_time, snd_strerror(err));
           return err;
      }
      err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
      if (err < 0) {
           printf("Unable to get period size for playback: %s\n", 
snd_strerror(err));
           return err;
      }
      period_size = size;
      /* write the parameters to device */
      err = snd_pcm_hw_params(handle, params);
      if (err < 0) {
           printf("Unable to set hw params for playback: %s\n", 
snd_strerror(err));
           return err;
      }
      return 0;
}



static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams) {

            int err;
           
            /*pegar os parametros atuais swparams*/
            err = snd_pcm_sw_params_current(handle, swparams);
            if (err < 0) {
                printf("Unable to determine current swparams for 
playback: %s\n", snd_strerror(err));
                return err;
            }
            /*Começa a transferência quando o buffer está quase cheio*/
            /*(buffer_size / avail_min) * avail_min */
            err = snd_pcm_sw_params_set_avail_min(handle, swparams, 
(buffer_size / period_size) * period_size);
            if (err < 0) {
                printf("Unable to set start threshold mode for playback: 
%s\n", snd_strerror(err));
                return err;
            }
            /* allow the transfer when at least period_size samples can 
be processed */
          /* or disable this mechanism when period event is enabled (aka 
interrupt like style processing) */
          err = snd_pcm_sw_params_set_avail_min(handle, swparams, 
period_event ? buffer_size : period_size);
          if (err < 0) {
                 printf("Unable to set avail min for playback: %s\n", 
snd_strerror(err));
                  return err;
         }
          /* enable period events when requested */
         if (period_event) {
                  err = snd_pcm_sw_params_set_period_event(handle, 
swparams, 1);
                  if (err < 0) {
                          printf("Unable to set period event: %s\n", 
snd_strerror(err));
                          return err;
                 }
          }
          /* write the parameters to the playback device */
          err = snd_pcm_sw_params(handle, swparams);
          if (err < 0) {
                  printf("Unable to set sw params for playback: %s\n", 
snd_strerror(err));
                  return err;
          }
          return 0;
 }

/* Tenta recuperar estados de underrun e suspend */

static int xrun_recovery(snd_pcm_t *handle, int err)
{
            if (verbose)
                    printf("stream recovery\n");
            if (err == -EPIPE) {      //under-run*/
                    err = snd_pcm_prepare(handle);
                    if (err < 0)
                                printf("Can't recovery from underrun, 
prepare failed: %s\n", snd_strerror(err));
                    return 0;
            } else if (err == -ESTRPIPE) {
                    while ((err = snd_pcm_resume(handle)) == -EAGAIN)
                            sleep(1); /*espera pela release flag*/
                    if (err < 0) {
                            err = snd_pcm_prepare(handle);
                            if (err < 0)
                                    printf("Can't recovery from suspend, 
prepare failed: %s\n", snd_strerror(err));
                            }
                            return 0;
                    }
                    return err;
}

/* Metodo de transferência *WRITE-ONLY* */
static int write_loop(snd_pcm_t *handle,
                             signed short *samples,
                             snd_pcm_channel_area_t *areas)
{
        double phase = 0;
        signed short *ptr;
        int err, cptr;
       
        while(1) {
            generate_sine(areas, 0, period_size, &phase);
            ptr = samples;
            cptr = period_size;
            while (cptr > 0) {
                    err = snd_pcm_writei(handle, ptr, cptr);
                    if (err == -EAGAIN)
                                 continue;
                    if (err < 0) {
                         if (xrun_recovery(handle, err) < 0) {
                                 printf("Write error: %s\n", 
snd_strerror(err));
                                 exit(EXIT_FAILURE);
                         }//if
                         ptr += err * channels;
                         cptr -= err;
                   }//if
                    }//if

         }//while
}


 /*
 *   Método de transferência - write and wait por espaço no buffer
 */

static int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, 
unsigned int count)
{
        unsigned short revents;

        while (1) {
                 poll(ufds, count, -1);
                 snd_pcm_poll_descriptors_revents(handle, ufds, count, 
&revents);
                 if (revents & POLLERR)
                        return -EIO;
                 if (revents & POLLOUT)
                        return 0;
        }
}


static int write_and_poll_loop(snd_pcm_t *handle,
                                 signed short *samples,
                                 snd_pcm_channel_area_t *areas)
  {
          struct pollfd *ufds;
          double phase = 0;
          signed short *ptr;
          int err, count, cptr, init;
 
          count = snd_pcm_poll_descriptors_count (handle);
          if (count <= 0) {
                  printf("Invalid poll descriptors count\n");
                  return count;
          }
 
          ufds = malloc(sizeof(struct pollfd) * count);
          if (ufds == NULL) {
                  printf("No enough memory\n");
                  return -ENOMEM;
          }
          if ((err = snd_pcm_poll_descriptors(handle, ufds, count)) < 0) {
                  printf("Unable to obtain poll descriptors for 
playback: %s\n", snd_strerror(err));
                  return err;
          }
 
          init = 1;
          while (1) {
                  if (!init) {
                          err = wait_for_poll(handle, ufds, count);
                          if (err < 0) {
                                 if (snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ||
                                      snd_pcm_state(handle) == 
SND_PCM_STATE_SUSPENDED) {
                                          err = snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                          if (xrun_recovery(handle, err) 
< 0) {
                                                  printf("Write error: 
%s\n", snd_strerror(err));
                                                  exit(EXIT_FAILURE);
                                          }
                                          init = 1;
                                  } else {
                                          printf("Wait for poll failed\n");
                                         return err;
                                  }
                          }
                  }
 
                  generate_sine(areas, 0, period_size, &phase);
                  ptr = samples;
                 cptr = period_size;
                  while (cptr > 0) {
                          err = snd_pcm_writei(handle, ptr, cptr);
                          if (err < 0) {
                                  if (xrun_recovery(handle, err) < 0) {
                                          printf("Write error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  init = 1;
                                 break;  /* skip one period */
                          }
                          if (snd_pcm_state(handle) == 
SND_PCM_STATE_RUNNING)
                                  init = 0;
                          ptr += err * channels;
                          cptr -= err;
                         if (cptr == 0)
                                  break;
                           /* it is possible, that the initial buffer 
cannot store */
                          /* all data from the last period, so wait 
awhile */
                          err = wait_for_poll(handle, ufds, count);
                          if (err < 0) {
                                  if (snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ||
                                     snd_pcm_state(handle) == 
SND_PCM_STATE_SUSPENDED) {
                                          err = snd_pcm_state(handle) == 
SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                          if (xrun_recovery(handle, err) 
< 0) {
                                                  printf("Write error: 
%s\n", snd_strerror(err));
                                                  exit(EXIT_FAILURE);
                                          }
                                          init = 1;
                                  } else {
                                          printf("Wait for poll failed\n");
                                         return err;
                                  }
                          }
                 }
          }
}



/*
*  Metodo de transferencia - Notificação assincrona
*/


 struct async_private_data {
         signed short *samples;
         snd_pcm_channel_area_t *areas;
         double phase;
 };
 

static void async_callback(snd_async_handler_t *ahandler)
{
         snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
         struct async_private_data *data = 
snd_async_handler_get_callback_private(ahandler);
          signed short *samples = data->samples;
          snd_pcm_channel_area_t *areas = data->areas;
         snd_pcm_sframes_t avail;
          int err;
         
         avail = snd_pcm_avail_update(handle);
          while (avail >= period_size) {
                 generate_sine(areas, 0, period_size, &data->phase);
                  err = snd_pcm_writei(handle, samples, period_size);
                  if (err < 0) {
                          printf("Write error: %s\n", snd_strerror(err));
                         exit(EXIT_FAILURE);
                 }
                  if (err != period_size) {
                          printf("Write error: written %i expected 
%li\n", err, period_size);
                         exit(EXIT_FAILURE);
                 }
                  avail = snd_pcm_avail_update(handle);
          }
}


static int async_loop(snd_pcm_t *handle,
                        signed short *samples,
                       snd_pcm_channel_area_t *areas)
  {
          struct async_private_data data;
         snd_async_handler_t *ahandler;
          int err, count;
 
         data.samples = samples;
          data.areas = areas;
         data.phase = 0;
          err = snd_async_add_pcm_handler(&ahandler, handle, 
async_callback, &data);
          if (err < 0) {
                  printf("Unable to register async handler\n");
                  exit(EXIT_FAILURE);
         }
         for (count = 0; count < 2; count++) {
                 generate_sine(areas, 0, period_size, &data.phase);
                  err = snd_pcm_writei(handle, samples, period_size);
                  if (err < 0) {
                         printf("Initial write error: %s\n", 
snd_strerror(err));
                         exit(EXIT_FAILURE);
                  }
                  if (err != period_size) {
                          printf("Initial write error: written %i 
expected %li\n", err, period_size);
                         exit(EXIT_FAILURE);
                  }
          }
          if (snd_pcm_state(handle) == SND_PCM_STATE_PREPARED) {
                  err = snd_pcm_start(handle);
                  if (err < 0) {
                         printf("Start error: %s\n", snd_strerror(err));
                          exit(EXIT_FAILURE);
                  }
          }
 
         /* because all other work is done in the signal handler,
             suspend the process */
          while (1) {
                  sleep(1);
          }
}

 /*
 *   Transfer method - asynchronous notification + direct write
 */
 
  static void async_direct_callback(snd_async_handler_t *ahandler)
  {
          snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
          struct async_private_data *data = 
snd_async_handler_get_callback_private(ahandler);
          const snd_pcm_channel_area_t *my_areas;
          snd_pcm_uframes_t offset, frames, size;
          snd_pcm_sframes_t avail, commitres;
          snd_pcm_state_t state;
          int first = 0, err;
         
          while (1) {
                  state = snd_pcm_state(handle);
                  if (state == SND_PCM_STATE_XRUN) {
                          err = xrun_recovery(handle, -EPIPE);
                          if (err < 0) {
                                  printf("XRUN recovery failed: %s\n", 
snd_strerror(err));
                                  exit(EXIT_FAILURE);
                          }
                          first = 1;
                  } else if (state == SND_PCM_STATE_SUSPENDED) {
                          err = xrun_recovery(handle, -ESTRPIPE);
                          if (err < 0) {
                                  printf("SUSPEND recovery failed: 
%s\n", snd_strerror(err));
                                  exit(EXIT_FAILURE);
                          }
                  }
                  avail = snd_pcm_avail_update(handle);
                  if (avail < 0) {
                          err = xrun_recovery(handle, avail);
                          if (err < 0) {
                                  printf("avail update failed: %s\n", 
snd_strerror(err));
                                   exit(EXIT_FAILURE);
                          }
                          first = 1;
                          continue;
                  }
                  if (avail < period_size) {
                          if (first) {
                                  first = 0;
                                  err = snd_pcm_start(handle);
                                  if (err < 0) {
                                          printf("Start error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                 }
                         } else {
                                  break;
                          }
                          continue;
                  }
                 size = period_size;
                  while (size > 0) {
                          frames = size;
                          err = snd_pcm_mmap_begin(handle, &my_areas, 
&offset, &frames);
                          if (err < 0) {
                                  if ((err = xrun_recovery(handle, err)) 
< 0) {
                                          printf("MMAP begin avail 
error: %s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  first = 1;
                          }
                          generate_sine(my_areas, offset, frames, 
&data->phase);
                          commitres = snd_pcm_mmap_commit(handle, 
offset, frames);
                          if (commitres < 0 || 
(snd_pcm_uframes_t)commitres != frames) {
                                  if ((err = xrun_recovery(handle, 
commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                          printf("MMAP commit error: 
%s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  first = 1;
                          }
                          size -= frames;
                  }
         }
}


static int async_direct_loop(snd_pcm_t *handle,
                               signed short *samples ATTRIBUTE_UNUSED,
                               snd_pcm_channel_area_t *areas 
ATTRIBUTE_UNUSED)
  {
          struct async_private_data data;
          snd_async_handler_t *ahandler;
          const snd_pcm_channel_area_t *my_areas;
          snd_pcm_uframes_t offset, frames, size;
          snd_pcm_sframes_t commitres;
          int err, count;
 
          data.samples = NULL;    /* we do not require the global sample 
area for direct write */
          data.areas = NULL;      /* we do not require the global areas 
for direct write */
          data.phase = 0;
         err = snd_async_add_pcm_handler(&ahandler, handle, 
async_direct_callback, &data);
          if (err < 0) {
                  printf("Unable to register async handler\n");
                  exit(EXIT_FAILURE);
          }
          for (count = 0; count < 2; count++) {
                  size = period_size;
                  while (size > 0) {
                          frames = size;
                          err = snd_pcm_mmap_begin(handle, &my_areas, 
&offset, &frames);
                          if (err < 0) {
                                  if ((err = xrun_recovery(handle, err)) 
< 0) {
                                          printf("MMAP begin avail 
error: %s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                 }
                         }
                          generate_sine(my_areas, offset, frames, 
&data.phase);
                          commitres = snd_pcm_mmap_commit(handle, 
offset, frames);
                          if (commitres < 0 || 
(snd_pcm_uframes_t)commitres != frames) {
                                  if ((err = xrun_recovery(handle, 
commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                          printf("MMAP commit error: 
%s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                          }
                          size -= frames;
                   }
          }
          err = snd_pcm_start(handle);
          if (err < 0) {
                  printf("Start error: %s\n", snd_strerror(err));
                  exit(EXIT_FAILURE);
          }
 
         /* because all other work is done in the signal handler,
             suspend the process */
          while (1) {
                  sleep(1);
          }
}

 /*
 *   Transfer method - direct write only
 */
 
 static int direct_loop(snd_pcm_t *handle,
                         signed short *samples ATTRIBUTE_UNUSED,
                         snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED)
  {
          double phase = 0;
         const snd_pcm_channel_area_t *my_areas;
          snd_pcm_uframes_t offset, frames, size;
         snd_pcm_sframes_t avail, commitres;
          snd_pcm_state_t state;
          int err, first = 1;
 
          while (1) {
                  state = snd_pcm_state(handle);
                  if (state == SND_PCM_STATE_XRUN) {
                          err = xrun_recovery(handle, -EPIPE);
                          if (err < 0) {
                                 printf("XRUN recovery failed: %s\n", 
snd_strerror(err));
                                  return err;
                          }
                          first = 1;
                 } else if (state == SND_PCM_STATE_SUSPENDED) {
                         err = xrun_recovery(handle, -ESTRPIPE);
                          if (err < 0) {
                                  printf("SUSPEND recovery failed: 
%s\n", snd_strerror(err));
                                   return err;
                          }
                  }
                  avail = snd_pcm_avail_update(handle);
                  if (avail < 0) {
                          err = xrun_recovery(handle, avail);
                          if (err < 0) {
                                  printf("avail update failed: %s\n", 
snd_strerror(err));
                                  return err;
                          }
                          first = 1;
                          continue;
                  }
                  if (avail < period_size) {
                          if (first) {
                                  first = 0;
                                  err = snd_pcm_start(handle);
                                  if (err < 0) {
                                          printf("Start error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                          } else {
                                  err = snd_pcm_wait(handle, -1);
                                  if (err < 0) {
                                          if ((err = 
xrun_recovery(handle, err)) < 0) {
                                                  printf("snd_pcm_wait 
error: %s\n", snd_strerror(err));
                                                  exit(EXIT_FAILURE);
                                          }
                                          first = 1;
                                  }
                          }
                          continue;
                  }
                  size = period_size;
                  while (size > 0) {
                           frames = size;
                          err = snd_pcm_mmap_begin(handle, &my_areas, 
&offset, &frames);
                          if (err < 0) {
                                 if ((err = xrun_recovery(handle, err)) 
< 0) {
                                          printf("MMAP begin avail 
error: %s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                  first = 1;
                         }
                          generate_sine(my_areas, offset, frames, &phase);
                          commitres = snd_pcm_mmap_commit(handle, 
offset, frames);
                          if (commitres < 0 || 
(snd_pcm_uframes_t)commitres != frames) {
                                 if ((err = xrun_recovery(handle, 
commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                          printf("MMAP commit error: 
%s\n", snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                  }
                                 first = 1;
                          }
                          size -= frames;
                  }
          }
}

/*
 *   Transfer method - direct write only using mmap_write functions
 */
 
 static int direct_write_loop(snd_pcm_t *handle,
                               signed short *samples,
                              snd_pcm_channel_area_t *areas)
 {
         double phase = 0;
          signed short *ptr;
          int err, cptr;
 
          while (1) {
                  generate_sine(areas, 0, period_size, &phase);
                 ptr = samples;
                  cptr = period_size;
                  while (cptr > 0) {
                          err = snd_pcm_mmap_writei(handle, ptr, cptr);
                          if (err == -EAGAIN)
                                  continue;
                          if (err < 0) {
                                  if (xrun_recovery(handle, err) < 0) {
                                          printf("Write error: %s\n", 
snd_strerror(err));
                                          exit(EXIT_FAILURE);
                                 }
                                 break;  /* skip one period */
                         }
                          ptr += err * channels;
                          cptr -= err;
                  }
          }
}

struct transfer_method {
       const char *name;
       snd_pcm_access_t access;
       int (*transfer_loop)(snd_pcm_t *handle,
                            signed short *samples,
                            snd_pcm_channel_area_t *areas);
};

static struct transfer_method transfer_methods[] = {
          { "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop },
          { "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, 
write_and_poll_loop },
          { "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop },
          { "async_direct", SND_PCM_ACCESS_MMAP_INTERLEAVED, 
async_direct_loop },
          { "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, 
direct_loop },
          { "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, 
direct_loop },
          { "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, 
direct_write_loop },
          { NULL, SND_PCM_ACCESS_RW_INTERLEAVED, NULL }
};



static void help(void)
{
         int k;
          printf(
  "Usage: pcm [OPTION]... [FILE]...\n"
  "-h,--help      help\n"
  "-D,--device    playback device\n"
  "-r,--rate      stream rate in Hz\n"
  "-c,--channels  count of channels in stream\n"
  "-f,--frequency sine wave frequency in Hz\n"
  "-b,--buffer    ring buffer size in us\n"
  "-p,--period    period size in us\n"
  "-m,--method    transfer method\n"
  "-o,--format    sample format\n"
  "-v,--verbose   show the PCM setup parameters\n"
  "-n,--noresample  do not resample\n"
  "-e,--pevent    enable poll event after each period\n"
  "\n");
          printf("Recognized sample formats are:");
         for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
                  const char *s = snd_pcm_format_name(k);
                  if (s)
                          printf(" %s", s);
          }
          printf("\n");
          printf("Recognized transfer methods are:");
          for (k = 0; transfer_methods[k].name; k++)
                  printf(" %s", transfer_methods[k].name);
          printf("\n");
}



int main (int argc, char *argv[])
{
            struct option long_option[] =
                {
                     {"help", 0, NULL, 'h'},
                     {"device", 1, NULL, 'd'},
                     {"rate", 1, NULL, 'r'},
                     {"channels", 1, NULL, 'c'},
                     {"frequency", 1, NULL, 'f'},
                     {"buffer", 1, NULL, 'b'},
                     {"period", 1, NULL, 'p'},
                     {"method", 1, NULL, 'm'},
                     {"format", 1, NULL, 'o'},
                     {"verbose", 1, NULL, 'v'},
                     {"noresample", 1, NULL, 'n'},
                     {"pevent", 1, NULL, 'e'},
                     {NULL, 0, NULL, 0},
                };
               
                snd_pcm_t *handle;                            //ponteiro 
para pcm handle
                int err, morehelp;
                snd_pcm_hw_params_t *hwparams;                
//parametros de hardware
                snd_pcm_sw_params_t *swparams;                
//parametros de software
                int method = 0;
                signed short *samples;
                unsigned int chn;
                snd_pcm_channel_area_t *areas;

                //snd_pcm_hw_params_alloca(&hwparams);
                //snd_pcm_sw_params_alloca(&swparams);
               
                morehelp = 0;
                while (1) {
                            int c;
                            if ((c = getopt_long(argc, argv, 
"hd:r:c:f:b:p:m:o:vne", long_option, NULL)) < 0)
                                    break;
                            switch(c) {
                            case 'h':
                                        morehelp++;
                                        break;
                            case 'd':
                                        device = strdup(optarg);
                                        break;
                            case 'r':
                                        rate = atoi(optarg);
                                        rate = rate < 4000 ? 4000 : rate;
                                        rate = rate > 196000 ? 19600 : rate;
                                        break;
                         case 'c':
                              channels = atoi(optarg);
                              channels = channels < 1 ? 1 : channels;
                              channels = channels > 1024 ? 1024 : channels;
                              break;
                     case 'f':
                              freq = atoi(optarg);
                              freq = freq < 50 ? 50 : freq;
                              freq = freq > 5000 ? 5000 : freq;
                              break;
                     case 'b':
                              buffer_time = atoi(optarg);
                              buffer_time = buffer_time < 1000 ? 1000 : 
buffer_time;
                              buffer_time = buffer_time > 1000000 ? 
1000000 : buffer_time;
                              break;
                     case 'p':
                              period_time = atoi(optarg);
                              period_time = period_time < 1000 ? 1000 : 
period_time;
                              period_time = period_time > 1000000 ? 
1000000 : period_time;
                              break;
                     case 'm':
                              for (method = 0; 
transfer_methods[method].name; method++)
                                              if 
(!strcasecmp(transfer_methods[method].name, optarg))
                                              break;
                              if (transfer_methods[method].name == NULL)
                                      method = 0;
                              break;
                     case 'o':
                              for (format = 0; format < 
SND_PCM_FORMAT_LAST; format++) {
                                      const char *format_name = 
snd_pcm_format_name(format);
                                      if (format_name)
                                              if 
(!strcasecmp(format_name, optarg))
                                              break;
                              }
                              if (format == SND_PCM_FORMAT_LAST)
                                     format = SND_PCM_FORMAT_S16;
                              break;
                     case 'v':
                              verbose = 1;
                              break;
                     case 'n':
                              resample = 0;
                              break;
                      case 'e':
                              period_event = 1;
                              break;
                     }//switch
              }//while
             
              if(morehelp) {
                          help();
                          return 0;
              }

                //cria um novo output objeto
                err = snd_output_stdio_attach(&output, &stdout, 0);
                if (err < 0) {
                        printf("Output failed: %s\n", snd_strerror(err));
                        return 0;
                }
               
                printf("Playback device is %s\n", device);
                printf("Stream parameters are %iHz, %s, %i channels\n", 
rate, snd_pcm_format_name(format), channels);
                printf("sine wave rate is %i %.4fHz\n", freq);
                printf("Using transfer method: %s\n", 
transfer_methods[method].name);
               
                if ((err = snd_pcm_open(&handle, device, 
SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
                        printf("Playback open error: %s\n", 
snd_strerror(err));
                        return 0;
                }
               
                if ((err = set_hwparams(handle, hwparams, 
transfer_methods[method].access)) < 0) {
                  printf("Setting of hwparams failed: %s\n", 
snd_strerror(err));
                  exit(EXIT_FAILURE);
            }
            if ((err = set_swparams(handle, swparams)) < 0) {
                  printf("Setting of swparams failed: %s\n", 
snd_strerror(err));
                  exit(EXIT_FAILURE);
           }
 
            if (verbose > 0)
                  snd_pcm_dump(handle, output);
               
            samples = malloc((period_size * channels * 
snd_pcm_format_physical_width(format)) / 8);
            if (samples == NULL) {
                  printf("No enough memory\n");
                  exit(EXIT_FAILURE);
            }
         
            areas = calloc(channels, sizeof(snd_pcm_channel_area_t));
            if (areas == NULL) {
                  printf("No enough memory\n");
                  exit(EXIT_FAILURE);
            }
            for (chn = 0; chn < channels; chn++) {
                  areas[chn].addr = samples;
                  areas[chn].first = chn * 
snd_pcm_format_physical_width(format);
                  areas[chn].step = channels * 
snd_pcm_format_physical_width(format);
             }
 
            err = transfer_methods[method].transfer_loop(handle, 
samples, areas);
            if (err < 0)
                  printf("Transfer failed: %s\n", snd_strerror(err));
 
            free(areas);
            free(samples);
            snd_pcm_close(handle);
            return 0;
}



Any ideas of what might be happening?? I've been looking for a 
reasonable explanation but i don't find any related error o online.

Tks in advanced!

Tks!

-------------------

Guilherme Longo
Dept. Eng. da Computação
Unaerp

Linux User - #484927

*Before Asking
http://www.istf.com.br/?page=perguntas

!- I'd rather die on my feet than live on my knees -!



Takashi Iwai wrote:
> At Fri, 19 Jun 2009 02:50:35 +0300,
> Maxim Levitsky wrote:
>   
>> Hi,
>>
>> Due to lack of time, I didn't update kernel on my desktop system.
>> Now I notice that analog loopback go removed. Why?
>>     
>
> Because it harms than helps more often.  I've got tons of bug reports
> and been upset just because users blindly set "Analog Loopback" mixer
> switch and lost their sound output.  This is no mixer element that
> behaves intuitively -- it shuts out PCM output instead of adding the
> analog loopback like other hardwares.
>
> The feature is still available, though.  You just need to give the
> driver an instruction via sysfs.  Namely, write to sysfs files
> corresponding to the IDT codec like
> 	# echo "loopback yes" > /sys/class/sound/hwC0D0/hints
> 	# echo 1 > /sys/class/sound/hwC0D0/reconfig
> Then the driver will reconfigure with the loopback mixer element.
> 	
> I have a patch series to add this with a "patch" firmware file to
> make it easier, which I'm going to send an RFC to this ML soon later.
> Take a look at topic/hda-patch branch on sound-unstable tree.
>
>
> thanks,
>
> Takashi
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
>
>   

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

* Re: segfault when setting swparams! help
  2009-06-19  7:27   ` segfault when setting swparams! help Guilherme
@ 2009-06-19  7:31     ` Takashi Iwai
  2009-06-19  7:43       ` segfault when setting swparams! help - SOLVED Guilherme
  0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2009-06-19  7:31 UTC (permalink / raw)
  To: Guilherme; +Cc: alsa-devel

At Fri, 19 Jun 2009 04:27:58 -0300,
Guilherme wrote:
> 
>                 //snd_pcm_hw_params_alloca(&hwparams);
>                 //snd_pcm_sw_params_alloca(&swparams);

Uncomment these.


Takashi

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

* Re: segfault when setting swparams! help - SOLVED
  2009-06-19  7:31     ` Takashi Iwai
@ 2009-06-19  7:43       ` Guilherme
  0 siblings, 0 replies; 14+ messages in thread
From: Guilherme @ 2009-06-19  7:43 UTC (permalink / raw)
  To: Takashi Iwai, alsa-devel

Thanks Takashi.
Its solved the problem.

Tks!

-------------------

Guilherme Longo
Dept. Eng. da Computação
Unaerp

Linux User - #484927

*Before Asking
http://www.istf.com.br/?page=perguntas

!- I'd rather die on my feet than live on my knees -!



Takashi Iwai wrote:
> At Fri, 19 Jun 2009 04:27:58 -0300,
> Guilherme wrote:
>   
>>                 //snd_pcm_hw_params_alloca(&hwparams);
>>                 //snd_pcm_sw_params_alloca(&swparams);
>>     
>
> Uncomment these.
>
>
> Takashi
>
>   

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19  6:32 ` Takashi Iwai
  2009-06-19  7:27   ` segfault when setting swparams! help Guilherme
@ 2009-06-19  8:21   ` Maxim Levitsky
  2009-06-19  8:23     ` Takashi Iwai
  2009-06-19 18:18   ` Maxim Levitsky
  2 siblings, 1 reply; 14+ messages in thread
From: Maxim Levitsky @ 2009-06-19  8:21 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Maxim Levitsky

On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> At Fri, 19 Jun 2009 02:50:35 +0300,
> Maxim Levitsky wrote:
> > 
> > Hi,
> > 
> > Due to lack of time, I didn't update kernel on my desktop system.
> > Now I notice that analog loopback go removed. Why?
> 
> Because it harms than helps more often.  I've got tons of bug reports
> and been upset just because users blindly set "Analog Loopback" mixer
> switch and lost their sound output.  This is no mixer element that
> behaves intuitively -- it shuts out PCM output instead of adding the
> analog loopback like other hardwares.

Here it doesn't shut PCM.
I just hear input in headphones, mixed with output.
I suspect that this feature might not work correctly on newer devices
that ones I have added.

> 
> The feature is still available, though.  You just need to give the
> driver an instruction via sysfs.  Namely, write to sysfs files
> corresponding to the IDT codec like
> 	# echo "loopback yes" > /sys/class/sound/hwC0D0/hints
> 	# echo 1 > /sys/class/sound/hwC0D0/reconfig
> Then the driver will reconfigure with the loopback mixer element.
> 	
> I have a patch series to add this with a "patch" firmware file to
> make it easier, which I'm going to send an RFC to this ML soon later.
> Take a look at topic/hda-patch branch on sound-unstable tree.
> 
> 
> thanks,
> 
> Takashi

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19  8:21   ` Why analog loopback of sigmatel devices got removed? Maxim Levitsky
@ 2009-06-19  8:23     ` Takashi Iwai
  2009-06-19 11:36       ` Maxim Levitsky
  0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2009-06-19  8:23 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: alsa-devel

At Fri, 19 Jun 2009 11:21:41 +0300,
Maxim Levitsky wrote:
> 
> On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > At Fri, 19 Jun 2009 02:50:35 +0300,
> > Maxim Levitsky wrote:
> > > 
> > > Hi,
> > > 
> > > Due to lack of time, I didn't update kernel on my desktop system.
> > > Now I notice that analog loopback go removed. Why?
> > 
> > Because it harms than helps more often.  I've got tons of bug reports
> > and been upset just because users blindly set "Analog Loopback" mixer
> > switch and lost their sound output.  This is no mixer element that
> > behaves intuitively -- it shuts out PCM output instead of adding the
> > analog loopback like other hardwares.
> 
> Here it doesn't shut PCM.
> I just hear input in headphones, mixed with output.
> I suspect that this feature might not work correctly on newer devices
> that ones I have added.

Possibly...


Takashi

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19  8:23     ` Takashi Iwai
@ 2009-06-19 11:36       ` Maxim Levitsky
  2009-06-19 12:50         ` Takashi Iwai
  0 siblings, 1 reply; 14+ messages in thread
From: Maxim Levitsky @ 2009-06-19 11:36 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Maxim Levitsky

On Fri, 2009-06-19 at 10:23 +0200, Takashi Iwai wrote:
> At Fri, 19 Jun 2009 11:21:41 +0300,
> Maxim Levitsky wrote:
> > 
> > On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > > At Fri, 19 Jun 2009 02:50:35 +0300,
> > > Maxim Levitsky wrote:
> > > > 
> > > > Hi,
> > > > 
> > > > Due to lack of time, I didn't update kernel on my desktop system.
> > > > Now I notice that analog loopback go removed. Why?
> > > 
> > > Because it harms than helps more often.  I've got tons of bug reports
> > > and been upset just because users blindly set "Analog Loopback" mixer
> > > switch and lost their sound output.  This is no mixer element that
> > > behaves intuitively -- it shuts out PCM output instead of adding the
> > > analog loopback like other hardwares.
> > 
> > Here it doesn't shut PCM.
> > I just hear input in headphones, mixed with output.
> > I suspect that this feature might not work correctly on newer devices
> > that ones I have added.
> 
> Possibly...

Probably IDT removed the analog mixer in quest for better quality.

I think it should work fine for "STAC..." parts.

Anyway lets put it back at least for my STAC9227, OK?

Best regards,
	Maxim Levitsky

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19 11:36       ` Maxim Levitsky
@ 2009-06-19 12:50         ` Takashi Iwai
  2009-06-19 14:55           ` Maxim Levitsky
  0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2009-06-19 12:50 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: alsa-devel

At Fri, 19 Jun 2009 14:36:39 +0300,
Maxim Levitsky wrote:
> 
> On Fri, 2009-06-19 at 10:23 +0200, Takashi Iwai wrote:
> > At Fri, 19 Jun 2009 11:21:41 +0300,
> > Maxim Levitsky wrote:
> > > 
> > > On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > > > At Fri, 19 Jun 2009 02:50:35 +0300,
> > > > Maxim Levitsky wrote:
> > > > > 
> > > > > Hi,
> > > > > 
> > > > > Due to lack of time, I didn't update kernel on my desktop system.
> > > > > Now I notice that analog loopback go removed. Why?
> > > > 
> > > > Because it harms than helps more often.  I've got tons of bug reports
> > > > and been upset just because users blindly set "Analog Loopback" mixer
> > > > switch and lost their sound output.  This is no mixer element that
> > > > behaves intuitively -- it shuts out PCM output instead of adding the
> > > > analog loopback like other hardwares.
> > > 
> > > Here it doesn't shut PCM.
> > > I just hear input in headphones, mixed with output.
> > > I suspect that this feature might not work correctly on newer devices
> > > that ones I have added.
> > 
> > Possibly...
> 
> Probably IDT removed the analog mixer in quest for better quality.
> 
> I think it should work fine for "STAC..." parts.
> 
> Anyway lets put it back at least for my STAC9227, OK?

You can still use it just by adjusting the sysfs (and in near future
via a patch file), so I'm not going to take it back for the default.


Takashi

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19 12:50         ` Takashi Iwai
@ 2009-06-19 14:55           ` Maxim Levitsky
  0 siblings, 0 replies; 14+ messages in thread
From: Maxim Levitsky @ 2009-06-19 14:55 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Maxim Levitsky

On Fri, 2009-06-19 at 14:50 +0200, Takashi Iwai wrote:
> At Fri, 19 Jun 2009 14:36:39 +0300,
> Maxim Levitsky wrote:
> > 
> > On Fri, 2009-06-19 at 10:23 +0200, Takashi Iwai wrote:
> > > At Fri, 19 Jun 2009 11:21:41 +0300,
> > > Maxim Levitsky wrote:
> > > > 
> > > > On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > > > > At Fri, 19 Jun 2009 02:50:35 +0300,
> > > > > Maxim Levitsky wrote:
> > > > > > 
> > > > > > Hi,
> > > > > > 
> > > > > > Due to lack of time, I didn't update kernel on my desktop system.
> > > > > > Now I notice that analog loopback go removed. Why?
> > > > > 
> > > > > Because it harms than helps more often.  I've got tons of bug reports
> > > > > and been upset just because users blindly set "Analog Loopback" mixer
> > > > > switch and lost their sound output.  This is no mixer element that
> > > > > behaves intuitively -- it shuts out PCM output instead of adding the
> > > > > analog loopback like other hardwares.
> > > > 
> > > > Here it doesn't shut PCM.
> > > > I just hear input in headphones, mixed with output.
> > > > I suspect that this feature might not work correctly on newer devices
> > > > that ones I have added.
> > > 
> > > Possibly...
> > 
> > Probably IDT removed the analog mixer in quest for better quality.
> > 
> > I think it should work fine for "STAC..." parts.
> > 
> > Anyway lets put it back at least for my STAC9227, OK?
> 
> You can still use it just by adjusting the sysfs (and in near future
> via a patch file), so I'm not going to take it back for the default.
Thanks....

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19  6:32 ` Takashi Iwai
  2009-06-19  7:27   ` segfault when setting swparams! help Guilherme
  2009-06-19  8:21   ` Why analog loopback of sigmatel devices got removed? Maxim Levitsky
@ 2009-06-19 18:18   ` Maxim Levitsky
  2009-06-19 18:44     ` Takashi Iwai
  2 siblings, 1 reply; 14+ messages in thread
From: Maxim Levitsky @ 2009-06-19 18:18 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Maxim Levitsky

On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> echo "loopback yes" > /sys/class/sound/hwC0D0/hints


This is unmerged  feature?

root@MAIN:/home/maxim# cat /sys/class/sound/hwC0D2/
dev        device/    power/     subsystem/ uevent     


I use -git of the kernel


Regards,
	Maxim Levitsky

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19 18:18   ` Maxim Levitsky
@ 2009-06-19 18:44     ` Takashi Iwai
  2009-06-19 21:05       ` Maxim Levitsky
  0 siblings, 1 reply; 14+ messages in thread
From: Takashi Iwai @ 2009-06-19 18:44 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: alsa-devel

At Fri, 19 Jun 2009 21:18:49 +0300,
Maxim Levitsky wrote:
> 
> On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > echo "loopback yes" > /sys/class/sound/hwC0D0/hints
> 
> 
> This is unmerged  feature?
> 
> root@MAIN:/home/maxim# cat /sys/class/sound/hwC0D2/
> dev        device/    power/     subsystem/ uevent     
> 
> 
> I use -git of the kernel

Set CONFIG_SND_HDA_RECONFIG=y.


Takashi

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19 18:44     ` Takashi Iwai
@ 2009-06-19 21:05       ` Maxim Levitsky
  2009-06-20  7:11         ` Takashi Iwai
  0 siblings, 1 reply; 14+ messages in thread
From: Maxim Levitsky @ 2009-06-19 21:05 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel, Maxim Levitsky

On Fri, 2009-06-19 at 20:44 +0200, Takashi Iwai wrote:
> At Fri, 19 Jun 2009 21:18:49 +0300,
> Maxim Levitsky wrote:
> > 
> > On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > > echo "loopback yes" > /sys/class/sound/hwC0D0/hints
> > 
> > 
> > This is unmerged  feature?
> > 
> > root@MAIN:/home/maxim# cat /sys/class/sound/hwC0D2/
> > dev        device/    power/     subsystem/ uevent     
> > 
> > 
> > I use -git of the kernel
> 
> Set CONFIG_SND_HDA_RECONFIG=y.
> 
> 
> Takashi

Ok, I see it now, but  then I put these commands in /etc/rc.local



echo  "loopback=yes" > /sys/class/sound/hwC0D2/hints
echo 1 > /sys/class/sound/hwC0D2/reconfig


and I get this, and almost empty mixer


[   57.353168] hda-codec: reconfiguring
[   57.426105] stac92xx_auto_fill_dac_nids: No available DAC for pin 0xd
[   59.121418] e1000e 0000:00:19.0: irq 29 for MSI/MSI-X
[   59.172115] e1000e 0000:00:19.0: irq 29 for MSI/MSI-X
[   60.585005] e1000e: eth0 NIC Link is Up 100 Mbps Full Duplex, Flow
Control: RX/TX
[   60.585011] 0000:00:19.0: eth0: 10/100 speed: disabling TSO



I had to reload the driver and apply the above commands to make it and
loopback work...


Why? It all did work fine before.


Regards,
	Maxim Levitsky

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

* Re: Why analog loopback of sigmatel devices got removed?
  2009-06-19 21:05       ` Maxim Levitsky
@ 2009-06-20  7:11         ` Takashi Iwai
  0 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2009-06-20  7:11 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: alsa-devel

At Sat, 20 Jun 2009 00:05:01 +0300,
Maxim Levitsky wrote:
> 
> On Fri, 2009-06-19 at 20:44 +0200, Takashi Iwai wrote:
> > At Fri, 19 Jun 2009 21:18:49 +0300,
> > Maxim Levitsky wrote:
> > > 
> > > On Fri, 2009-06-19 at 08:32 +0200, Takashi Iwai wrote:
> > > > echo "loopback yes" > /sys/class/sound/hwC0D0/hints
> > > 
> > > 
> > > This is unmerged  feature?
> > > 
> > > root@MAIN:/home/maxim# cat /sys/class/sound/hwC0D2/
> > > dev        device/    power/     subsystem/ uevent     
> > > 
> > > 
> > > I use -git of the kernel
> > 
> > Set CONFIG_SND_HDA_RECONFIG=y.
> > 
> > 
> > Takashi
> 
> Ok, I see it now, but  then I put these commands in /etc/rc.local
> 
> 
> 
> echo  "loopback=yes" > /sys/class/sound/hwC0D2/hints
> echo 1 > /sys/class/sound/hwC0D2/reconfig
> 
> 
> and I get this, and almost empty mixer
> 
> 
> [   57.353168] hda-codec: reconfiguring
> [   57.426105] stac92xx_auto_fill_dac_nids: No available DAC for pin 0xd

Yeah, something is wrong here.
Could you run alsa-info.sh with --no-upload option at this stage, and
attach the generated file?


thanks,

Takashi

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

end of thread, other threads:[~2009-06-20  7:11 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-18 23:50 Why analog loopback of sigmatel devices got removed? Maxim Levitsky
2009-06-19  6:32 ` Takashi Iwai
2009-06-19  7:27   ` segfault when setting swparams! help Guilherme
2009-06-19  7:31     ` Takashi Iwai
2009-06-19  7:43       ` segfault when setting swparams! help - SOLVED Guilherme
2009-06-19  8:21   ` Why analog loopback of sigmatel devices got removed? Maxim Levitsky
2009-06-19  8:23     ` Takashi Iwai
2009-06-19 11:36       ` Maxim Levitsky
2009-06-19 12:50         ` Takashi Iwai
2009-06-19 14:55           ` Maxim Levitsky
2009-06-19 18:18   ` Maxim Levitsky
2009-06-19 18:44     ` Takashi Iwai
2009-06-19 21:05       ` Maxim Levitsky
2009-06-20  7:11         ` Takashi Iwai

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.