Commit 7f6f7753 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

  - CS46xx driver - removed unused variable
  - USB code
    - pass struct usb_interface pointer to the usb-midi parser.
      in usb-midi functions, this instance is used instead of parsing
      the interface from dev and ifnum.
    - allocate the descriptor buffer only for parsing the audio device.
    - clean up, new probe/disconnect callbacks for 2.4 API.
    - added the support for Yamaha and Midiman devices.                                                  
parent 0f8328bc
......@@ -1577,7 +1577,6 @@ int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip)
int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
unsigned int flags;
/* turn on amplifier */
chip->active_ctrl(chip, 1);
......
......@@ -1410,7 +1410,6 @@ int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src)
{
dsp_spos_instance_t * ins = chip->dsp_spos_instance;
dsp_scb_descriptor_t * parent_scb;
unsigned int flags;
snd_assert (src->parent_scb_ptr == NULL, return -EINVAL );
snd_assert(ins->master_mix_scb !=NULL, return -EINVAL );
......
......@@ -122,7 +122,7 @@ static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list,
* Remove a node from the chain. Called with the lock asserted
*/
static void __sound_remove_unit(struct sound_unit **list, int unit)
static struct sound_unit *__sound_remove_unit(struct sound_unit **list, int unit)
{
while(*list)
{
......@@ -130,13 +130,12 @@ static void __sound_remove_unit(struct sound_unit **list, int unit)
if(p->unit_minor==unit)
{
*list=p->next;
devfs_unregister (p->de);
kfree(p);
return;
return p;
}
list=&(p->next);
}
printk(KERN_ERR "Sound device %d went missing!\n", unit);
return NULL;
}
/*
......@@ -189,9 +188,15 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
static void sound_remove_unit(struct sound_unit **list, int unit)
{
struct sound_unit *p;
spin_lock(&sound_loader_lock);
__sound_remove_unit(list, unit);
p = __sound_remove_unit(list, unit);
spin_unlock(&sound_loader_lock);
if (p) {
devfs_unregister (p->de);
kfree(p);
}
}
/*
......
......@@ -1308,12 +1308,10 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
* entry point for linux usb interface
*/
static void * _usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id);
static void _usb_audio_disconnect(struct usb_device *dev, void *ptr);
#ifdef OLD_USB
#define usb_audio_probe _usb_audio_probe
#define usb_audio_disconnect _usb_audio_disconnect
static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id);
static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
#else
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *id);
......@@ -1828,7 +1826,8 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, unsigned char *buffer, i
* parse audio control descriptor and create pcm/midi streams
*/
static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, int ifnum,
static int snd_usb_create_midi_interface(snd_usb_audio_t *chip,
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk);
static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
......@@ -1868,7 +1867,7 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
}
if (iface->altsetting[0].bInterfaceClass == USB_CLASS_AUDIO &&
iface->altsetting[0].bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
if (snd_usb_create_midi_interface(chip, j, NULL) < 0) {
if (snd_usb_create_midi_interface(chip, iface, NULL) < 0) {
snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j);
continue;
}
......@@ -1889,7 +1888,8 @@ static int snd_usb_create_streams(snd_usb_audio_t *chip, int ctrlif,
return 0;
}
static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, int ifnum,
static int snd_usb_create_midi_interface(snd_usb_audio_t *chip,
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk)
{
#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
......@@ -1906,18 +1906,20 @@ static int snd_usb_create_midi_interface(snd_usb_audio_t *chip, int ifnum,
strcpy(seq_device->name, chip->card->shortname);
umidi = (snd_usb_midi_t *)SNDRV_SEQ_DEVICE_ARGPTR(seq_device);
umidi->chip = chip;
umidi->ifnum = ifnum;
umidi->iface = iface;
umidi->ifnum = iface->altsetting->bInterfaceNumber;
umidi->quirk = quirk;
umidi->seq_client = -1;
#endif
return 0;
}
static inline int snd_usb_create_quirk(snd_usb_audio_t *chip, int ifnum,
static inline int snd_usb_create_quirk(snd_usb_audio_t *chip,
struct usb_interface *iface,
const snd_usb_audio_quirk_t *quirk)
{
/* in the future, there may be quirks for PCM devices */
return snd_usb_create_midi_interface(chip, ifnum, quirk);
return snd_usb_create_midi_interface(chip, iface, quirk);
}
......@@ -2068,18 +2070,18 @@ static int alloc_desc_buffer(struct usb_device *dev, int index, unsigned char **
* only at the first time. the successive calls of this function will
* append the pcm interface to the corresponding card.
*/
static void *_usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
static void *snd_usb_audio_probe(struct usb_device *dev,
struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_config_descriptor *config = dev->actconfig;
const snd_usb_audio_quirk_t *quirk = (const snd_usb_audio_quirk_t *)id->driver_info;
unsigned char *buffer;
unsigned int index;
int i, buflen;
int i;
snd_card_t *card;
snd_usb_audio_t *chip;
int ifnum = intf->altsetting->bInterfaceNumber;
if (quirk && ifnum != quirk->ifnum)
if (quirk && quirk->ifnum != QUIRK_ANY_INTERFACE && ifnum != quirk->ifnum)
goto __err_val;
if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
......@@ -2087,11 +2089,6 @@ static void *_usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
goto __err_val;
}
index = dev->actconfig - config;
buflen = alloc_desc_buffer(dev, index, &buffer);
if (buflen <= 0)
goto __err_val;
/*
* found a config. now register to ALSA
*/
......@@ -2133,12 +2130,24 @@ static void *_usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
}
if (!quirk) {
if (snd_usb_create_streams(chip, ifnum, buffer, buflen) < 0)
/* USB audio interface */
unsigned char *buffer;
unsigned int index;
int buflen;
index = dev->actconfig - config;
buflen = alloc_desc_buffer(dev, index, &buffer);
if (buflen <= 0)
goto __error;
if (snd_usb_create_mixer(chip, ifnum, buffer, buflen) < 0)
if (snd_usb_create_streams(chip, ifnum, buffer, buflen) < 0 ||
snd_usb_create_mixer(chip, ifnum, buffer, buflen) < 0) {
kfree(buffer);
goto __error;
}
kfree(buffer);
} else {
if (snd_usb_create_quirk(chip, ifnum, quirk) < 0)
/* USB midi interface */
if (snd_usb_create_quirk(chip, intf, quirk) < 0)
goto __error;
}
......@@ -2151,12 +2160,10 @@ static void *_usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
chip->num_interfaces++;
up(&register_mutex);
kfree(buffer);
return chip;
__error:
up(&register_mutex);
kfree(buffer);
__err_val:
return NULL;
}
......@@ -2165,7 +2172,7 @@ static void *_usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
* we need to take care of counter, since disconnection can be called also
* many times as well as usb_audio_probe().
*/
static void _usb_audio_disconnect(struct usb_device *dev, void *ptr)
static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
{
snd_usb_audio_t *chip;
......@@ -2179,17 +2186,32 @@ static void _usb_audio_disconnect(struct usb_device *dev, void *ptr)
}
#ifndef OLD_USB
#ifdef OLD_USB
/*
* new 2.5 USB kernel API
* 2.4 USB kernel API
*/
static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
return snd_usb_audio_probe(dev, usb_ifnum_to_if(dev, ifnum), id);
}
static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
{
snd_usb_audio_disconnect(dev, ptr);
}
#else
/*
* new 2.5 USB kernel API
*/
static int usb_audio_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
void *chip;
chip = _usb_audio_probe(interface_to_usbdev(intf),
intf->altsetting->bInterfaceNumber, id);
chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
if (chip) {
dev_set_drvdata(&intf->dev, chip);
return 0;
......@@ -2199,8 +2221,8 @@ static int usb_audio_probe(struct usb_interface *intf,
static void usb_audio_disconnect(struct usb_interface *intf)
{
_usb_audio_disconnect(interface_to_usbdev(intf),
dev_get_drvdata(&intf->dev));
snd_usb_audio_disconnect(interface_to_usbdev(intf),
dev_get_drvdata(&intf->dev));
}
#endif
......
......@@ -58,6 +58,8 @@
#define EP_GENERAL 0x01
#define MS_GENERAL 0x01
#define MIDI_IN_JACK 0x02
#define MIDI_OUT_JACK 0x03
/* endpoint attributes */
#define EP_ATTR_MASK 0x0c
......@@ -146,22 +148,34 @@ struct snd_usb_audio {
/*
* Information about devices with broken descriptors
*/
#define QUIRK_ANY_INTERFACE -1
#define QUIRK_MIDI_FIXED_ENDPOINT 0
#define QUIRK_MIDI_YAMAHA 1
#define QUIRK_MIDI_MIDIMAN 2
typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
struct snd_usb_audio_quirk {
const char *vendor_name;
const char *product_name;
int ifnum;
int16_t ifnum;
int16_t type;
const void *data;
};
/* MIDI specific */
struct snd_usb_midi_endpoint_info {
int16_t epnum; /* ep number, -1 autodetect */
uint16_t out_cables; /* bitmask */
uint16_t in_cables; /* bitmask */
} endpoints[MIDI_MAX_ENDPOINTS];
/* data for QUIRK_MIDI_FIXED_ENDPOINT */
struct snd_usb_midi_endpoint_info {
int16_t epnum; /* ep number, -1 autodetect */
uint16_t out_cables; /* bitmask */
uint16_t in_cables; /* bitmask */
};
/* for QUIRK_MIDI_YAMAHA, data is NULL */
/* for QUIRK_MIDI_MIDIMAN, data is the number of ports */
/*
* USB MIDI sequencer device data
*/
......@@ -173,6 +187,7 @@ typedef struct snd_usb_midi_in_endpoint snd_usb_midi_in_endpoint_t;
struct snd_usb_midi {
/* filled by usbaudio.c */
snd_usb_audio_t *chip;
struct usb_interface *iface;
int ifnum;
const snd_usb_audio_quirk_t *quirk;
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment