]> rtime.felk.cvut.cz Git - linux-imx.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Jun 2010 14:39:57 +0000 (07:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 27 Jun 2010 14:39:57 +0000 (07:39 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: usb/endpoint, fix dangling pointer use
  ALSA: asihpi - Get rid of incorrect "long" types and casts.
  ASoC: DaVinci: Fix McASP hardware FIFO configuration
  ALSA: hda - Fix line-in for mb5 model MacBook (Pro) 5,1 / 5,2
  ALSA: usb-audio: fix UAC2 control value queries
  ALSA: usb-audio: parse UAC2 sample rate ranges correctly
  ALSA: usb-audio: fix control messages for USB_RECIP_INTERFACE
  ALSA: usb-audio: add check for faulty clock in parse_audio_format_rates_v2()
  ALSA: hda - Don't check capture source mixer if no ADC is available

sound/pci/asihpi/hpi6205.c
sound/pci/hda/patch_realtek.c
sound/soc/davinci/davinci-mcasp.c
sound/usb/clock.c
sound/usb/endpoint.c
sound/usb/format.c
sound/usb/helper.h
sound/usb/mixer.c

index e89991ea35439c7ea122777ee3bd284feaa47535..3b44134482266ff5f17ddeb301b258846a34eb77 100644 (file)
@@ -941,11 +941,11 @@ static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
 
 }
 
-static long outstream_get_space_available(struct hpi_hostbuffer_status
+static u32 outstream_get_space_available(struct hpi_hostbuffer_status
        *status)
 {
-       return status->size_in_bytes - ((long)(status->host_index) -
-               (long)(status->dSP_index));
+       return status->size_in_bytes - (status->host_index -
+               status->dSP_index);
 }
 
 static void outstream_write(struct hpi_adapter_obj *pao,
@@ -954,7 +954,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
        struct hpi_hw_obj *phw = pao->priv;
        struct bus_master_interface *interface = phw->p_interface_buffer;
        struct hpi_hostbuffer_status *status;
-       long space_available;
+       u32 space_available;
 
        if (!phw->outstream_host_buffer_size[phm->obj_index]) {
                /* there  is no BBM buffer, write via message */
@@ -1007,7 +1007,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
        }
 
        space_available = outstream_get_space_available(status);
-       if (space_available < (long)phm->u.d.u.data.data_size) {
+       if (space_available < phm->u.d.u.data.data_size) {
                phr->error = HPI_ERROR_INVALID_DATASIZE;
                return;
        }
@@ -1018,7 +1018,7 @@ static void outstream_write(struct hpi_adapter_obj *pao,
                && hpios_locked_mem_valid(&phw->outstream_host_buffers[phm->
                                obj_index])) {
                u8 *p_bbm_data;
-               long l_first_write;
+               u32 l_first_write;
                u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
 
                if (hpios_locked_mem_get_virt_addr(&phw->
@@ -1248,9 +1248,9 @@ static void instream_start(struct hpi_adapter_obj *pao,
        hw_message(pao, phm, phr);
 }
 
-static long instream_get_bytes_available(struct hpi_hostbuffer_status *status)
+static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
 {
-       return (long)(status->dSP_index) - (long)(status->host_index);
+       return status->dSP_index - status->host_index;
 }
 
 static void instream_read(struct hpi_adapter_obj *pao,
@@ -1259,9 +1259,9 @@ static void instream_read(struct hpi_adapter_obj *pao,
        struct hpi_hw_obj *phw = pao->priv;
        struct bus_master_interface *interface = phw->p_interface_buffer;
        struct hpi_hostbuffer_status *status;
-       long data_available;
+       u32 data_available;
        u8 *p_bbm_data;
-       long l_first_read;
+       u32 l_first_read;
        u8 *p_app_data = (u8 *)phm->u.d.u.data.pb_data;
 
        if (!phw->instream_host_buffer_size[phm->obj_index]) {
@@ -1272,7 +1272,7 @@ static void instream_read(struct hpi_adapter_obj *pao,
 
        status = &interface->instream_host_buffer_status[phm->obj_index];
        data_available = instream_get_bytes_available(status);
-       if (data_available < (long)phm->u.d.u.data.data_size) {
+       if (data_available < phm->u.d.u.data.data_size) {
                phr->error = HPI_ERROR_INVALID_DATASIZE;
                return;
        }
index fc767b6b4785df50cabd947ddc3174a8d13d5978..f1ce7d7f5aa3b4649e083b92e80b9fd57508c839 100644 (file)
@@ -2619,16 +2619,18 @@ static int alc_build_controls(struct hda_codec *codec)
        }
 
        /* assign Capture Source enums to NID */
-       kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
-       if (!kctl)
-               kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
-       for (i = 0; kctl && i < kctl->count; i++) {
-               hda_nid_t *nids = spec->capsrc_nids;
-               if (!nids)
-                       nids = spec->adc_nids;
-               err = snd_hda_add_nid(codec, kctl, i, nids[i]);
-               if (err < 0)
-                       return err;
+       if (spec->capsrc_nids || spec->adc_nids) {
+               kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
+               if (!kctl)
+                       kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
+               for (i = 0; kctl && i < kctl->count; i++) {
+                       hda_nid_t *nids = spec->capsrc_nids;
+                       if (!nids)
+                               nids = spec->adc_nids;
+                       err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+                       if (err < 0)
+                               return err;
+               }
        }
        if (spec->cap_mixer) {
                const char *kname = kctl ? kctl->id.name : NULL;
@@ -6948,7 +6950,7 @@ static struct hda_input_mux mb5_capture_source = {
        .num_items = 3,
        .items = {
                { "Mic", 0x1 },
-               { "Line", 0x2 },
+               { "Line", 0x7 },
                { "CD", 0x4 },
        },
 };
@@ -7469,8 +7471,8 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
        HDA_BIND_MUTE   ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
        HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
        HDA_BIND_MUTE   ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
-       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-       HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+       HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
+       HDA_CODEC_MUTE  ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
        HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_MUTE  ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
        HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
@@ -7853,10 +7855,9 @@ static struct hda_verb alc885_mb5_init_verbs[] = {
        {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
        {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
+       {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
        { }
 };
 
index 79f0f4ad242c1be8bfb00694ff1e011016942f90..d3955096d87214e842d3ba25d0e45aedf3fbcc12 100644 (file)
@@ -612,7 +612,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
                                                                NUMDMA_MASK);
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
                                ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
        }
 
        if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -623,7 +622,6 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
                                                                NUMDMA_MASK);
                mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
                                ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
        }
 }
 
index b7aadd614c70b378f6724f31d8883e82b2ced48c..b5855114667ef4976d0250630bc17dd3891fe912 100644 (file)
@@ -103,7 +103,8 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
        ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
                              UAC2_CS_CUR,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             UAC2_CX_CLOCK_SELECTOR << 8, selector_id << 8,
+                             UAC2_CX_CLOCK_SELECTOR << 8,
+                             snd_usb_ctrl_intf(chip) | (selector_id << 8),
                              &buf, sizeof(buf), 1000);
 
        if (ret < 0)
@@ -120,7 +121,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
 
        err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_CLOCK_VALID << 8, source_id << 8,
+                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
+                             snd_usb_ctrl_intf(chip) | (source_id << 8),
                              &data, sizeof(data), 1000);
 
        if (err < 0) {
@@ -269,7 +271,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
        data[3] = rate >> 24;
        if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
                                   USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                                  UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+                                  UAC2_CS_CONTROL_SAM_FREQ << 8,
+                                  snd_usb_ctrl_intf(chip) | (clock << 8),
                                   data, sizeof(data), 1000)) < 0) {
                snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
                           dev->devnum, iface, fmt->altsetting, rate);
@@ -278,7 +281,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 
        if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
                                   USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                  UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+                                  UAC2_CS_CONTROL_SAM_FREQ << 8,
+                                  snd_usb_ctrl_intf(chip) | (clock << 8),
                                   data, sizeof(data), 1000)) < 0) {
                snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
                           dev->devnum, iface, fmt->altsetting);
index 9593b91452b97f9564989d4ab1df7a32905b4e64..6f6596cf2b190d0e1f18860a4384bacddbec472f 100644 (file)
@@ -427,6 +427,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
                        kfree(fp->rate_table);
                        kfree(fp);
+                       fp = NULL;
                        continue;
                }
 
index 5367cd1e52d9dac9231077e829ca3e0869175de4..30364aba79ccb0e8bef307ccbe166d28799d7464 100644 (file)
@@ -205,6 +205,60 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
        return 0;
 }
 
+/*
+ * Helper function to walk the array of sample rate triplets reported by
+ * the device. The problem is that we need to parse whole array first to
+ * get to know how many sample rates we have to expect.
+ * Then fp->rate_table can be allocated and filled.
+ */
+static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
+                                       const unsigned char *data)
+{
+       int i, nr_rates = 0;
+
+       fp->rates = fp->rate_min = fp->rate_max = 0;
+
+       for (i = 0; i < nr_triplets; i++) {
+               int min = combine_quad(&data[2 + 12 * i]);
+               int max = combine_quad(&data[6 + 12 * i]);
+               int res = combine_quad(&data[10 + 12 * i]);
+               int rate;
+
+               if ((max < 0) || (min < 0) || (res < 0) || (max < min))
+                       continue;
+
+               /*
+                * for ranges with res == 1, we announce a continuous sample
+                * rate range, and this function should return 0 for no further
+                * parsing.
+                */
+               if (res == 1) {
+                       fp->rate_min = min;
+                       fp->rate_max = max;
+                       fp->rates = SNDRV_PCM_RATE_CONTINUOUS;
+                       return 0;
+               }
+
+               for (rate = min; rate <= max; rate += res) {
+                       if (fp->rate_table)
+                               fp->rate_table[nr_rates] = rate;
+                       if (!fp->rate_min || rate < fp->rate_min)
+                               fp->rate_min = rate;
+                       if (!fp->rate_max || rate > fp->rate_max)
+                               fp->rate_max = rate;
+                       fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+
+                       nr_rates++;
+
+                       /* avoid endless loop */
+                       if (res == 0)
+                               break;
+               }
+       }
+
+       return nr_rates;
+}
+
 /*
  * parse the format descriptor and stores the possible sample rates
  * on the audioformat table (audio class v2).
@@ -215,13 +269,20 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 {
        struct usb_device *dev = chip->dev;
        unsigned char tmp[2], *data;
-       int i, nr_rates, data_size, ret = 0;
+       int nr_triplets, data_size, ret = 0;
        int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fp->clock);
 
+       if (clock < 0) {
+               snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
+                               __func__, clock);
+               goto err;
+       }
+
        /* get the number of sample rates first by only fetching 2 bytes */
        ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
                              tmp, sizeof(tmp), 1000);
 
        if (ret < 0) {
@@ -230,8 +291,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
                goto err;
        }
 
-       nr_rates = (tmp[1] << 8) | tmp[0];
-       data_size = 2 + 12 * nr_rates;
+       nr_triplets = (tmp[1] << 8) | tmp[0];
+       data_size = 2 + 12 * nr_triplets;
        data = kzalloc(data_size, GFP_KERNEL);
        if (!data) {
                ret = -ENOMEM;
@@ -241,7 +302,8 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
        /* now get the full information */
        ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8, clock << 8,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
                              data, data_size, 1000);
 
        if (ret < 0) {
@@ -251,26 +313,28 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
                goto err_free;
        }
 
-       fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
+       /* Call the triplet parser, and make sure fp->rate_table is NULL.
+        * We just use the return value to know how many sample rates we
+        * will have to deal with. */
+       kfree(fp->rate_table);
+       fp->rate_table = NULL;
+       fp->nr_rates = parse_uac2_sample_rate_range(fp, nr_triplets, data);
+
+       if (fp->nr_rates == 0) {
+               /* SNDRV_PCM_RATE_CONTINUOUS */
+               ret = 0;
+               goto err_free;
+       }
+
+       fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
        if (!fp->rate_table) {
                ret = -ENOMEM;
                goto err_free;
        }
 
-       fp->nr_rates = 0;
-       fp->rate_min = fp->rate_max = 0;
-
-       for (i = 0; i < nr_rates; i++) {
-               int rate = combine_quad(&data[2 + 12 * i]);
-
-               fp->rate_table[fp->nr_rates] = rate;
-               if (!fp->rate_min || rate < fp->rate_min)
-                       fp->rate_min = rate;
-               if (!fp->rate_max || rate > fp->rate_max)
-                       fp->rate_max = rate;
-               fp->rates |= snd_pcm_rate_to_rate_bit(rate);
-               fp->nr_rates++;
-       }
+       /* Call the triplet parser again, but this time, fp->rate_table is
+        * allocated, so the rates will be stored */
+       parse_uac2_sample_rate_range(fp, nr_triplets, data);
 
 err_free:
        kfree(data);
index a6b0e51b3a9a2ebae41cb03d3ca80e06e4a07b09..09bd943c43bf736c72c915ce99f41180b6be88b9 100644 (file)
@@ -28,5 +28,9 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
 #define snd_usb_get_speed(dev) ((dev)->speed)
 #endif
 
+static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
+{
+       return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
+}
 
 #endif /* __USBAUDIO_HELPER_H */
index a060d005e20921089309569a9e8ebb9c9115b455..6939d0f517d9bd42928f87e7f6a4e9fd35bff9b4 100644 (file)
@@ -297,20 +297,27 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 {
-       unsigned char buf[14]; /* enough space for one range of 4 bytes */
+       unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
        unsigned char *val;
-       int ret;
+       int ret, size;
        __u8 bRequest;
 
-       bRequest = (request == UAC_GET_CUR) ?
-               UAC2_CS_CUR : UAC2_CS_RANGE;
+       if (request == UAC_GET_CUR) {
+               bRequest = UAC2_CS_CUR;
+               size = sizeof(__u16);
+       } else {
+               bRequest = UAC2_CS_RANGE;
+               size = sizeof(buf);
+       }
+
+       memset(buf, 0, sizeof(buf));
 
        ret = snd_usb_ctl_msg(cval->mixer->chip->dev,
                              usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
                              bRequest,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                              validx, cval->mixer->ctrlif | (cval->id << 8),
-                             buf, sizeof(buf), 1000);
+                             buf, size, 1000);
 
        if (ret < 0) {
                snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
@@ -318,6 +325,8 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
                return ret;
        }
 
+       /* FIXME: how should we handle multiple triplets here? */
+
        switch (request) {
        case UAC_GET_CUR:
                val = buf;