Commit 8fd667b0 authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

  - fixed oops in snd_rawmidi_info()
  - MTPAV driver - fixed spin-deadlock
  - ICE1712 - added Midiman M-Audio Delta1010LT support, fixed spin-deadlock
  - emu10k1 - fixed memory allocation inside spinlock (GFP_ATOMIC)
parent ac1d5c67
/* include/version.h. Generated automatically by configure. */
#define CONFIG_SND_VERSION "0.9.0rc3"
#define CONFIG_SND_DATE " (Mon Oct 14 16:41:26 2002 UTC)"
#define CONFIG_SND_DATE " (Tue Oct 22 14:30:41 2002 UTC)"
......@@ -15,7 +15,7 @@
* 2002-04-04 Tomas Kasparek better rates handling (allow non-standard rates)
*/
/* $Id: sa11xx-uda1341.c,v 1.4 2002/08/06 18:03:25 perex Exp $ */
/* $Id: sa11xx-uda1341.c,v 1.5 2002/10/21 18:28:19 perex Exp $ */
#include <sound/driver.h>
#include <linux/module.h>
......
......@@ -518,7 +518,11 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file)
int snd_rawmidi_info(snd_rawmidi_substream_t *substream, snd_rawmidi_info_t *info)
{
snd_rawmidi_t *rmidi = substream->rmidi;
snd_rawmidi_t *rmidi;
if (substream == NULL)
return -ENODEV;
rmidi = substream->rmidi;
memset(info, 0, sizeof(*info));
info->card = rmidi->card->number;
info->device = rmidi->device;
......
......@@ -19,19 +19,8 @@
*
*/
#ifdef ALSA_BUILD
#include "config.h"
#endif
#include <linux/version.h>
#include <linux/config.h>
#ifdef ALSA_BUILD
#if defined(CONFIG_MODVERSIONS) && !defined(__GENKSYMS__) && !defined(__DEPEND__)
#define MODVERSIONS
#include <linux/modversions.h>
#include "sndversions.h"
#endif
#endif
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
......
/*
* MOTU Midi Timepiece ALSA Main routines
* Copyright by Michael T. Mayers (c) Jan 09, 2000
* mail: tweakoz@pacbell.net
* mail: michael@tweakoz.com
* Thanks to John Galbraith
*
* This program is free software; you can redistribute it and/or modify
......@@ -421,25 +421,19 @@ static void snd_mtpav_output_timer(unsigned long data)
spin_unlock(&chip->spinlock);
}
/* spinlock held! */
static void snd_mtpav_add_output_timer(mtpav_t *chip)
{
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
chip->timer.function = snd_mtpav_output_timer;
chip->timer.data = (unsigned long) mtp_card;
chip->timer.expires = 1 + jiffies;
add_timer(&chip->timer);
spin_unlock_irqrestore(&chip->spinlock, flags);
}
/* spinlock held! */
static void snd_mtpav_remove_output_timer(mtpav_t *chip)
{
unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags);
del_timer(&chip->timer);
spin_unlock_irqrestore(&chip->spinlock, flags);
}
/*
......@@ -510,8 +504,11 @@ static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte)
return;
port = &mcrd->ports[mcrd->inmidiport];
if (port->mode & MTPAV_MODE_INPUT_TRIGGERED)
if (port->mode & MTPAV_MODE_INPUT_TRIGGERED) {
spin_unlock(&mcrd->spinlock);
snd_rawmidi_receive(port->input, &inbyte, 1);
spin_lock(&mcrd->spinlock);
}
}
static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte)
......
......@@ -74,6 +74,9 @@ CONFIG_SND_FM801
CONFIG_SND_ICE1712
Say 'Y' or 'M' to include support for ICE1712 (Envy24) based soundcards.
Currently supported hardware is: MidiMan M Audio - Delta 1010(LT), Dio 2496,
Delta 66/44, Audiophile 24/96; Hoontech SoundTrack DSP 24 (Value);
TerraTec - EWX 24/96, EWS 88MT, EWS 88D, DMX 6Fire.
CONFIG_SND_INTEL8X0
Say 'Y' or 'M' to include support for Intel8x0 based soundcards,
......
......@@ -413,7 +413,7 @@ static int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
snd_runtime_check(emu, return -EINVAL);
snd_runtime_check(handler, return -EINVAL);
irq = kmalloc(sizeof(*irq), GFP_KERNEL);
irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
if (irq == NULL)
return -ENOMEM;
irq->handler = handler;
......
......@@ -593,7 +593,7 @@ static void snd_es1371_codec_write(ac97_t *ac97,
}
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
snd_printk("codec write timeout at 0x%lx [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
snd_printk("codec write timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
}
static unsigned short snd_es1371_codec_read(ac97_t *ac97,
......@@ -641,14 +641,14 @@ static unsigned short snd_es1371_codec_read(ac97_t *ac97,
}
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
if (++fail > 10) {
snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
snd_printk("codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), reg, inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
}
goto __again;
}
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
snd_printk("es1371: codec read timeout at 0x%lx [0x%lx]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
snd_printk("es1371: codec read timeout at 0x%lx [0x%x]\n", ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
return 0;
}
......
......@@ -51,12 +51,18 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
tmp |= ak->add_flags;
if (ak->cif) {
tmp |= ak->codecs_mask; /* start without chip select */
} else {
tmp &= ~ak->codecs_mask; /* chip select low */
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
udelay(1);
tmp &= ~ak->mask_flags;
if (ak->cs_mask == ak->cs_addr) {
if (ak->cif) {
tmp |= ak->cs_mask; /* start without chip select */
} else {
tmp &= ~ak->cs_mask; /* chip select low */
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
udelay(1);
}
} else {
tmp &= ~ak->cs_mask;
tmp |= ak->cs_addr;
}
addr &= 0x07;
......@@ -79,13 +85,18 @@ void snd_ice1712_ak4524_write(ice1712_t *ice, int chip,
else
ak->ipga_gain[chip][addr-4] = data;
if (ak->cif) {
/* assert a cs pulse to trigger */
tmp &= ~ak->codecs_mask;
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
udelay(1);
if (ak->cs_mask == ak->cs_addr) {
if (ak->cif) {
/* assert a cs pulse to trigger */
tmp &= ~ak->cs_mask;
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
udelay(1);
}
tmp |= ak->cs_mask; /* chip select high to trigger */
} else {
tmp &= ~ak->cs_mask;
tmp |= ak->cs_none; /* deselect address */
}
tmp |= ak->codecs_mask; /* chip select high to trigger */
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
udelay(1);
......
......@@ -83,8 +83,13 @@ static unsigned char ap_cs8427_codec_select(ice1712_t *ice)
{
unsigned char tmp;
tmp = snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA);
tmp |= ICE1712_DELTA_AP_CCLK | ICE1712_DELTA_AP_CS_CODEC;
tmp &= ~ICE1712_DELTA_AP_CS_DIGITAL;
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010LT) {
tmp &= ~ICE1712_DELTA_1010LT_CS;
tmp |= ICE1712_DELTA_1010LT_CCLK | ICE1712_DELTA_1010LT_CS_CS8427;
} else { /* Audiophile */
tmp |= ICE1712_DELTA_AP_CCLK | ICE1712_DELTA_AP_CS_CODEC;
tmp &= ~ICE1712_DELTA_AP_CS_DIGITAL;
}
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
udelay(5);
return tmp;
......@@ -93,7 +98,12 @@ static unsigned char ap_cs8427_codec_select(ice1712_t *ice)
/* deassert chip select */
static void ap_cs8427_codec_deassert(ice1712_t *ice, unsigned char tmp)
{
tmp |= ICE1712_DELTA_AP_CS_DIGITAL;
if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DELTA1010LT) {
tmp &= ~ICE1712_DELTA_1010LT_CS;
tmp |= ICE1712_DELTA_1010LT_CS_NONE;
} else { /* Audiophile */
tmp |= ICE1712_DELTA_AP_CS_DIGITAL;
}
snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, tmp);
}
......@@ -227,12 +237,25 @@ static int delta_spdif_stream_put(ice1712_t *ice, snd_ctl_elem_value_t * ucontro
static int delta_ak4524_start(ice1712_t *ice, unsigned char *saved, int chip)
{
snd_ice1712_save_gpio_status(ice, saved);
ice->ak4524.codecs_mask = chip == 0 ? ICE1712_DELTA_CODEC_CHIP_A : ICE1712_DELTA_CODEC_CHIP_B;
ice->ak4524.cs_mask =
ice->ak4524.cs_addr = chip == 0 ? ICE1712_DELTA_CODEC_CHIP_A :
ICE1712_DELTA_CODEC_CHIP_B;
return 0;
}
/*
* AK4524 on Delta1010LT to choose the chip address
*/
static int delta1010lt_ak4524_start(ice1712_t *ice, unsigned char *saved, int chip)
{
snd_ice1712_save_gpio_status(ice, saved);
ice->ak4524.cs_mask = ICE1712_DELTA_1010LT_CS;
ice->ak4524.cs_addr = chip << 4;
return 0;
}
/*
* change the rate of AK4524 on Delta 44/66 and AP
* change the rate of AK4524 on Delta 44/66, AP, 1010LT
*/
static void delta_ak4524_set_rate_val(ice1712_t *ice, unsigned char val)
{
......@@ -319,6 +342,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
ice->num_total_dacs = ice->omni ? 8 : 4;
break;
case ICE1712_SUBDEVICE_DELTA1010:
case ICE1712_SUBDEVICE_DELTA1010LT:
ice->num_total_dacs = 8;
break;
}
......@@ -326,6 +350,7 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
/* initialize spdif */
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_AUDIOPHILE:
case ICE1712_SUBDEVICE_DELTA1010LT:
if ((err = snd_i2c_bus_create(ice->card, "ICE1712 GPIO 1", NULL, &ice->i2c)) < 0) {
snd_printk("unable to create I2C bus\n");
return err;
......@@ -358,8 +383,23 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_AP_DOUT;
ak->clk_mask = ICE1712_DELTA_AP_CCLK;
ak->codecs_mask = ICE1712_DELTA_AP_CS_CODEC; /* select AK4528 codec */
ak->cs_mask = ak->cs_addr = ICE1712_DELTA_AP_CS_CODEC; /* select AK4528 codec */
ak->cs_none = 0;
ak->add_flags = ICE1712_DELTA_AP_CS_DIGITAL; /* assert digital high */
ak->mask_flags = 0;
ak->ops.set_rate_val = delta_ak4524_set_rate_val;
snd_ice1712_ak4524_init(ice);
break;
case ICE1712_SUBDEVICE_DELTA1010LT:
ak->num_adcs = ak->num_dacs = 8;
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_1010LT_DOUT;
ak->clk_mask = ICE1712_DELTA_1010LT_CCLK;
ak->cs_mask = ak->cs_addr = 0; /* set later */
ak->cs_none = ICE1712_DELTA_1010LT_CS_NONE;
ak->add_flags = 0;
ak->mask_flags = 0;
ak->ops.start = delta1010lt_ak4524_start;
ak->ops.set_rate_val = delta_ak4524_set_rate_val;
snd_ice1712_ak4524_init(ice);
break;
......@@ -369,8 +409,10 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
ak->cif = 0; /* the default level of the CIF pin from AK4524 */
ak->data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA;
ak->clk_mask = ICE1712_DELTA_CODEC_SERIAL_CLOCK;
ak->codecs_mask = 0; /* set later */
ak->cs_mask = ak->cs_addr = 0; /* set later */
ak->cs_none = 0;
ak->add_flags = 0;
ak->mask_flags = 0;
ak->ops.start = delta_ak4524_start;
ak->ops.set_rate_val = delta_ak4524_set_rate_val;
snd_ice1712_ak4524_init(ice);
......@@ -387,6 +429,8 @@ static int __devinit snd_ice1712_delta_init(ice1712_t *ice)
static snd_kcontrol_new_t snd_ice1712_delta1010_wordclock_select __devinitdata =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
static snd_kcontrol_new_t snd_ice1712_delta1010lt_wordclock_select __devinitdata =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 1, 0);
static snd_kcontrol_new_t snd_ice1712_delta1010_wordclock_status __devinitdata =
ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_PCM, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
static snd_kcontrol_new_t snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
......@@ -414,6 +458,11 @@ static int __devinit snd_ice1712_delta_add_controls(ice1712_t *ice)
if (err < 0)
return err;
break;
case ICE1712_SUBDEVICE_DELTA1010LT:
err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_delta1010lt_wordclock_select, ice));
if (err < 0)
return err;
break;
}
/* normal spdif controls */
......
......@@ -26,6 +26,7 @@
#define DELTA_DEVICE_DESC \
"{MidiMan M Audio,Delta 1010},"\
"{MidiMan M Audio,Delta 1010LT},"\
"{MidiMan M Audio,Delta DiO 2496},"\
"{MidiMan M Audio,Delta 66},"\
"{MidiMan M Audio,Delta 44},"\
......@@ -46,7 +47,7 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
* MidiMan M-Audio Delta GPIO definitions
*/
/* MidiMan M-Audio Delta1010 */
/* MidiMan M-Audio Delta shared pins */
#define ICE1712_DELTA_DFS 0x01 /* fast/slow sample rate mode */
/* (>48kHz must be 1) */
#define ICE1712_DELTA_SPDIF_IN_STAT 0x02
......@@ -116,5 +117,19 @@ extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
#define ICE1712_DELTA_AP_CS_CODEC 0x20 /* AK4528 chip select */
/* low signal = select */
/* MidiMan M-Audio Delta1010LT definitions */
/* thanks to Anders Johansson <ajh@watri.uwa.edu.au> */
/* 0x01 = DFS */
#define ICE1712_DELTA_1010LT_CCLK 0x02 /* SPI clock (AK4524 + CS8427) */
#define ICE1712_DELTA_1010LT_DIN 0x04 /* data input (CS8427) */
#define ICE1712_DELTA_1010LT_DOUT 0x08 /* data output (AK4524 + CS8427) */
#define ICE1712_DELTA_1010LT_CS 0x70 /* mask for CS address */
#define ICE1712_DELTA_1010LT_CS_CHIP_A 0x00 /* AK4524 #0 */
#define ICE1712_DELTA_1010LT_CS_CHIP_B 0x10 /* AK4524 #1 */
#define ICE1712_DELTA_1010LT_CS_CHIP_C 0x20 /* AK4524 #2 */
#define ICE1712_DELTA_1010LT_CS_CHIP_D 0x30 /* AK4524 #3 */
#define ICE1712_DELTA_1010LT_CS_CS8427 0x40 /* CS8427 */
#define ICE1712_DELTA_1010LT_CS_NONE 0x50 /* nothing */
#define ICE1712_DELTA_1010LT_WORDCLOCK 0x80 /* sample clock source: 0 = Word Clock Input, 1 = S/PDIF Input ??? */
#endif /* __SOUND_DELTA_H */
......@@ -199,7 +199,7 @@ static int dmx6fire_ak4524_start(ice1712_t *ice, unsigned char *saved, int chip)
{
unsigned char tmp;
snd_ice1712_save_gpio_status(ice, saved);
tmp = ice->ak4524.codecs_mask = (1 << chip) & ICE1712_6FIRE_AK4524_CS_MASK;
tmp = ice->ak4524.cs_mask = ice->ak4524.cs_addr = (1 << chip) & ICE1712_6FIRE_AK4524_CS_MASK;
tmp |= ICE1712_6FIRE_SERIAL_DATA |
ICE1712_6FIRE_SERIAL_CLOCK |
ICE1712_6FIRE_RW;
......@@ -221,16 +221,17 @@ static void snd_ice1712_ews_cs8404_spdif_write(ice1712_t *ice, unsigned char bit
snd_i2c_lock(ice->i2c);
switch (ice->eeprom.subvendor) {
case ICE1712_SUBDEVICE_EWS88MT:
snd_runtime_check(snd_i2c_sendbytes(ice->cs8404, &bits, 1) == 1, snd_i2c_unlock(ice->i2c); return);
snd_runtime_check(snd_i2c_sendbytes(ice->cs8404, &bits, 1) == 1, goto _error);
break;
case ICE1712_SUBDEVICE_EWS88D:
snd_runtime_check(snd_i2c_readbytes(ice->i2cdevs[0], bytes, 2) == 2, snd_i2c_unlock(ice->i2c); return);
snd_runtime_check(snd_i2c_readbytes(ice->i2cdevs[0], bytes, 2) == 2, goto _error);
if (bits != bytes[1]) {
bytes[1] = bits;
snd_runtime_check(snd_i2c_readbytes(ice->i2cdevs[0], bytes, 2) == 2, snd_i2c_unlock(ice->i2c); return);
snd_runtime_check(snd_i2c_readbytes(ice->i2cdevs[0], bytes, 2) == 2, goto _error);
}
break;
}
_error:
snd_i2c_unlock(ice->i2c);
}
......@@ -408,8 +409,9 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
ak->codecs_mask = 0; /* no chip select on gpio */
ak->cs_mask = ak->cs_addr = ak->cs_none = 0; /* no chip select on gpio */
ak->add_flags = ICE1712_EWS88_RW; /* set rw bit high */
ak->mask_flags = 0;
ak->ops.start = ews88mt_ak4524_start;
ak->ops.stop = ews88mt_ak4524_stop;
snd_ice1712_ak4524_init(ice);
......@@ -419,8 +421,10 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_EWS88_SERIAL_DATA;
ak->clk_mask = ICE1712_EWS88_SERIAL_CLOCK;
ak->codecs_mask = ICE1712_EWX2496_AK4524_CS;
ak->cs_mask = ak->cs_addr = ICE1712_EWX2496_AK4524_CS;
ak->cs_none = 0;
ak->add_flags = ICE1712_EWS88_RW; /* set rw bit high */
ak->mask_flags = 0;
ak->ops.start = ewx2496_ak4524_start;
snd_ice1712_ak4524_init(ice);
break;
......@@ -429,8 +433,10 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
ak->cif = 1; /* CIF high */
ak->data_mask = ICE1712_6FIRE_SERIAL_DATA;
ak->clk_mask = ICE1712_6FIRE_SERIAL_CLOCK;
ak->codecs_mask = 0; /* set later */
ak->cs_mask = ak->cs_addr = 0; /* set later */
ak->cs_none = 0;
ak->add_flags = ICE1712_6FIRE_RW; /* set rw bit high */
ak->mask_flags = 0;
ak->ops.start = dmx6fire_ak4524_start;
snd_ice1712_ak4524_init(ice);
break;
......@@ -562,6 +568,7 @@ static int snd_ice1712_ews88mt_input_sense_get(snd_kcontrol_t *kcontrol, snd_ctl
}
/* reversed; high = +4dBu, low = -10dBV */
ucontrol->value.enumerated.item[0] = data & (1 << channel) ? 0 : 1;
snd_i2c_unlock(ice->i2c);
return 0;
}
......
......@@ -246,8 +246,11 @@ struct snd_ak4524 {
unsigned int cif: 1;
unsigned char data_mask;
unsigned char clk_mask;
unsigned char codecs_mask;
unsigned char cs_mask;
unsigned char cs_addr;
unsigned char cs_none;
unsigned char add_flags;
unsigned char mask_flags;
struct snd_ak4524_ops {
int (*start)(ice1712_t *, unsigned char *, int);
void (*stop)(ice1712_t *, unsigned char *);
......
......@@ -25,7 +25,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: hammerfall_mem.c,v 1.3 2002/09/12 09:03:28 tiwai Exp $
$Id: hammerfall_mem.c,v 1.4 2002/10/21 18:28:25 perex Exp $
Tue Oct 17 2000 Jaroslav Kysela <perex@suse.cz>
......
CONFIG_SND_USB_AUDIO
Say 'Y' or 'M' to include support for USB audio devices.
To support USB MIDI devices, you need to enable ALSA sequencer support
(CONFIG_SND_SEQUENCER).
Say 'Y' or 'M' to include support for USB audio and USB MIDI devices.
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