sound fixes for 3.12-rc3
Nothing too serious here: a couple of compress-offload core fixes, Haswell HDMI audio fix, a fixup for new MacBook Airs and a few COEF setups for ALC283 mic problems. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iQIcBAABAgAGBQJSRXXaAAoJEGwxgFQ9KSmkpnEP/0yNW2kXvDTtDJ4ctu9b8MOK GGcmJdadTXWpEalRz9Ya2iCuhCI9etZ5HpjradtYtr2ZfYwtY3iYdqoZLHY4HdRm Ib8WU4fM0/xV839nGrEzojwBEulRVbs8BXw+VE7d9kgAHvrL69d0Uv243ZBV3mcU 6hNEVby0EFoA4jN2ATJ2ZTpHg9PT+Duy9hL7nBW0pdQL5TlYSdlLKq2Xs6xZ6+Os rzT1zXUmw5aovQbtSsGKhzFvjUKF4JenR9b8KzSepppVL5YUxgEgFMgRGCfTDSD8 XSf4w+QoJFIuOXPQu0Kuylny3n+2EA6tffAEkOgPs93x5TgZN9KqTMTuWfA4qRm9 nS6MU0uc5IOrQY84XoWxilGJUo3LL2xyk8BqLPDVp4m+JTfqZk3yWFX2EO4P8UCB wp4DoBbG429dIC5TTDTpfDghd8pEK7V4zqq4V5bz1LdYLJ8k+YmKcE1x5S0O6Ims QgZFJCgmx95yiOlIi/K5t6TngCGwSruEZIm+jbrRxXKBde1zm4/16ULUfLRAn6f+ b5eX3bcPVyJL7tXMNHlTYAbOdT9vREegCcMIk4nrbXypZaO3vwsYo4GlWTBRHdsE U+4Z3sc4C9fZwQIJaaJGXWA6i/CULyCcB6a+h741fkWDCiinTQdKLJxZc8D27Q89 dNah0gnJ/rLyTT6SY1nV =bi3p -----END PGP SIGNATURE----- Merge tag 'sound-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound fixes from Takashi Iwai: "Nothing too serious here: a couple of compress-offload core fixes, Haswell HDMI audio fix, a fixup for new MacBook Airs and a few COEF setups for ALC283 mic problems" * tag 'sound-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: ALSA: hda - Enable internal mic on a Thinkpad machine with ALC283 ALSA: hda - Fix Internal Mic boost can't control with ALC283 ALSA: hda - Add documentation for CS4208 fixups ALSA: hda - Add fixup for MacBook Air 6,1 and 6,2 with CS4208 codec ALSA : hda - not use assigned converters for all unused pins ALSA: compress: Make sure we trigger STOP before closing the stream. ALSA: compress: Fix compress device unregister.
This commit is contained in:
commit
a7301fcc12
|
@ -296,6 +296,12 @@ Cirrus Logic CS4206/4207
|
||||||
imac27 IMac 27 Inch
|
imac27 IMac 27 Inch
|
||||||
auto BIOS setup (default)
|
auto BIOS setup (default)
|
||||||
|
|
||||||
|
Cirrus Logic CS4208
|
||||||
|
===================
|
||||||
|
mba6 MacBook Air 6,1 and 6,2
|
||||||
|
gpio0 Enable GPIO 0 amp
|
||||||
|
auto BIOS setup (default)
|
||||||
|
|
||||||
VIA VT17xx/VT18xx/VT20xx
|
VIA VT17xx/VT18xx/VT20xx
|
||||||
========================
|
========================
|
||||||
auto BIOS setup (default)
|
auto BIOS setup (default)
|
||||||
|
|
|
@ -139,6 +139,18 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
||||||
static int snd_compr_free(struct inode *inode, struct file *f)
|
static int snd_compr_free(struct inode *inode, struct file *f)
|
||||||
{
|
{
|
||||||
struct snd_compr_file *data = f->private_data;
|
struct snd_compr_file *data = f->private_data;
|
||||||
|
struct snd_compr_runtime *runtime = data->stream.runtime;
|
||||||
|
|
||||||
|
switch (runtime->state) {
|
||||||
|
case SNDRV_PCM_STATE_RUNNING:
|
||||||
|
case SNDRV_PCM_STATE_DRAINING:
|
||||||
|
case SNDRV_PCM_STATE_PAUSED:
|
||||||
|
data->stream.ops->trigger(&data->stream, SNDRV_PCM_TRIGGER_STOP);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
data->stream.ops->free(&data->stream);
|
data->stream.ops->free(&data->stream);
|
||||||
kfree(data->stream.runtime->buffer);
|
kfree(data->stream.runtime->buffer);
|
||||||
kfree(data->stream.runtime);
|
kfree(data->stream.runtime);
|
||||||
|
@ -837,7 +849,8 @@ static int snd_compress_dev_disconnect(struct snd_device *device)
|
||||||
struct snd_compr *compr;
|
struct snd_compr *compr;
|
||||||
|
|
||||||
compr = device->device_data;
|
compr = device->device_data;
|
||||||
snd_unregister_device(compr->direction, compr->card, compr->device);
|
snd_unregister_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card,
|
||||||
|
compr->device);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,9 @@ enum {
|
||||||
/* 0x0009 - 0x0014 -> 12 test regs */
|
/* 0x0009 - 0x0014 -> 12 test regs */
|
||||||
/* 0x0015 - visibility reg */
|
/* 0x0015 - visibility reg */
|
||||||
|
|
||||||
|
/* Cirrus Logic CS4208 */
|
||||||
|
#define CS4208_VENDOR_NID 0x24
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cirrus Logic CS4210
|
* Cirrus Logic CS4210
|
||||||
*
|
*
|
||||||
|
@ -223,6 +226,16 @@ static const struct hda_verb cs_coef_init_verbs[] = {
|
||||||
{} /* terminator */
|
{} /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct hda_verb cs4208_coef_init_verbs[] = {
|
||||||
|
{0x01, AC_VERB_SET_POWER_STATE, 0x00}, /* AFG: D0 */
|
||||||
|
{0x24, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */
|
||||||
|
{0x24, AC_VERB_SET_COEF_INDEX, 0x0033},
|
||||||
|
{0x24, AC_VERB_SET_PROC_COEF, 0x0001}, /* A1 ICS */
|
||||||
|
{0x24, AC_VERB_SET_COEF_INDEX, 0x0034},
|
||||||
|
{0x24, AC_VERB_SET_PROC_COEF, 0x1C01}, /* A1 Enable, A Thresh = 300mV */
|
||||||
|
{} /* terminator */
|
||||||
|
};
|
||||||
|
|
||||||
/* Errata: CS4207 rev C0/C1/C2 Silicon
|
/* Errata: CS4207 rev C0/C1/C2 Silicon
|
||||||
*
|
*
|
||||||
* http://www.cirrus.com/en/pubs/errata/ER880C3.pdf
|
* http://www.cirrus.com/en/pubs/errata/ER880C3.pdf
|
||||||
|
@ -295,6 +308,8 @@ static int cs_init(struct hda_codec *codec)
|
||||||
/* init_verb sequence for C0/C1/C2 errata*/
|
/* init_verb sequence for C0/C1/C2 errata*/
|
||||||
snd_hda_sequence_write(codec, cs_errata_init_verbs);
|
snd_hda_sequence_write(codec, cs_errata_init_verbs);
|
||||||
snd_hda_sequence_write(codec, cs_coef_init_verbs);
|
snd_hda_sequence_write(codec, cs_coef_init_verbs);
|
||||||
|
} else if (spec->vendor_nid == CS4208_VENDOR_NID) {
|
||||||
|
snd_hda_sequence_write(codec, cs4208_coef_init_verbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_hda_gen_init(codec);
|
snd_hda_gen_init(codec);
|
||||||
|
@ -434,6 +449,29 @@ static const struct hda_pintbl mba42_pincfgs[] = {
|
||||||
{} /* terminator */
|
{} /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct hda_pintbl mba6_pincfgs[] = {
|
||||||
|
{ 0x10, 0x032120f0 }, /* HP */
|
||||||
|
{ 0x11, 0x500000f0 },
|
||||||
|
{ 0x12, 0x90100010 }, /* Speaker */
|
||||||
|
{ 0x13, 0x500000f0 },
|
||||||
|
{ 0x14, 0x500000f0 },
|
||||||
|
{ 0x15, 0x770000f0 },
|
||||||
|
{ 0x16, 0x770000f0 },
|
||||||
|
{ 0x17, 0x430000f0 },
|
||||||
|
{ 0x18, 0x43ab9030 }, /* Mic */
|
||||||
|
{ 0x19, 0x770000f0 },
|
||||||
|
{ 0x1a, 0x770000f0 },
|
||||||
|
{ 0x1b, 0x770000f0 },
|
||||||
|
{ 0x1c, 0x90a00090 },
|
||||||
|
{ 0x1d, 0x500000f0 },
|
||||||
|
{ 0x1e, 0x500000f0 },
|
||||||
|
{ 0x1f, 0x500000f0 },
|
||||||
|
{ 0x20, 0x500000f0 },
|
||||||
|
{ 0x21, 0x430000f0 },
|
||||||
|
{ 0x22, 0x430000f0 },
|
||||||
|
{} /* terminator */
|
||||||
|
};
|
||||||
|
|
||||||
static void cs420x_fixup_gpio_13(struct hda_codec *codec,
|
static void cs420x_fixup_gpio_13(struct hda_codec *codec,
|
||||||
const struct hda_fixup *fix, int action)
|
const struct hda_fixup *fix, int action)
|
||||||
{
|
{
|
||||||
|
@ -556,22 +594,23 @@ static int patch_cs420x(struct hda_codec *codec)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CS4208 support:
|
* CS4208 support:
|
||||||
* Its layout is no longer compatible with CS4206/CS4207, and the generic
|
* Its layout is no longer compatible with CS4206/CS4207
|
||||||
* parser seems working fairly well, except for trivial fixups.
|
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
|
CS4208_MBA6,
|
||||||
CS4208_GPIO0,
|
CS4208_GPIO0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct hda_model_fixup cs4208_models[] = {
|
static const struct hda_model_fixup cs4208_models[] = {
|
||||||
{ .id = CS4208_GPIO0, .name = "gpio0" },
|
{ .id = CS4208_GPIO0, .name = "gpio0" },
|
||||||
|
{ .id = CS4208_MBA6, .name = "mba6" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
|
static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
|
||||||
/* codec SSID */
|
/* codec SSID */
|
||||||
SND_PCI_QUIRK(0x106b, 0x7100, "MacBookPro 6,1", CS4208_GPIO0),
|
SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
|
||||||
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookPro 6,2", CS4208_GPIO0),
|
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
|
||||||
{} /* terminator */
|
{} /* terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -588,18 +627,35 @@ static void cs4208_fixup_gpio0(struct hda_codec *codec,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct hda_fixup cs4208_fixups[] = {
|
static const struct hda_fixup cs4208_fixups[] = {
|
||||||
|
[CS4208_MBA6] = {
|
||||||
|
.type = HDA_FIXUP_PINS,
|
||||||
|
.v.pins = mba6_pincfgs,
|
||||||
|
.chained = true,
|
||||||
|
.chain_id = CS4208_GPIO0,
|
||||||
|
},
|
||||||
[CS4208_GPIO0] = {
|
[CS4208_GPIO0] = {
|
||||||
.type = HDA_FIXUP_FUNC,
|
.type = HDA_FIXUP_FUNC,
|
||||||
.v.func = cs4208_fixup_gpio0,
|
.v.func = cs4208_fixup_gpio0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* correct the 0dB offset of input pins */
|
||||||
|
static void cs4208_fix_amp_caps(struct hda_codec *codec, hda_nid_t adc)
|
||||||
|
{
|
||||||
|
unsigned int caps;
|
||||||
|
|
||||||
|
caps = query_amp_caps(codec, adc, HDA_INPUT);
|
||||||
|
caps &= ~(AC_AMPCAP_OFFSET);
|
||||||
|
caps |= 0x02;
|
||||||
|
snd_hda_override_amp_caps(codec, adc, HDA_INPUT, caps);
|
||||||
|
}
|
||||||
|
|
||||||
static int patch_cs4208(struct hda_codec *codec)
|
static int patch_cs4208(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct cs_spec *spec;
|
struct cs_spec *spec;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
spec = cs_alloc_spec(codec, 0); /* no specific w/a */
|
spec = cs_alloc_spec(codec, CS4208_VENDOR_NID);
|
||||||
if (!spec)
|
if (!spec)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -609,6 +665,12 @@ static int patch_cs4208(struct hda_codec *codec)
|
||||||
cs4208_fixups);
|
cs4208_fixups);
|
||||||
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
||||||
|
|
||||||
|
snd_hda_override_wcaps(codec, 0x18,
|
||||||
|
get_wcaps(codec, 0x18) | AC_WCAP_STEREO);
|
||||||
|
cs4208_fix_amp_caps(codec, 0x18);
|
||||||
|
cs4208_fix_amp_caps(codec, 0x1b);
|
||||||
|
cs4208_fix_amp_caps(codec, 0x1c);
|
||||||
|
|
||||||
err = cs_parse_auto_config(codec);
|
err = cs_parse_auto_config(codec);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -1149,32 +1149,43 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void haswell_config_cvts(struct hda_codec *codec,
|
static void haswell_config_cvts(struct hda_codec *codec,
|
||||||
int pin_id, int mux_id)
|
hda_nid_t pin_nid, int mux_idx)
|
||||||
{
|
{
|
||||||
struct hdmi_spec *spec = codec->spec;
|
struct hdmi_spec *spec = codec->spec;
|
||||||
struct hdmi_spec_per_pin *per_pin;
|
hda_nid_t nid, end_nid;
|
||||||
int pin_idx, mux_idx;
|
int cvt_idx, curr;
|
||||||
int curr;
|
struct hdmi_spec_per_cvt *per_cvt;
|
||||||
int err;
|
|
||||||
|
|
||||||
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
|
/* configure all pins, including "no physical connection" ones */
|
||||||
per_pin = get_pin(spec, pin_idx);
|
end_nid = codec->start_nid + codec->num_nodes;
|
||||||
|
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
||||||
|
unsigned int wid_caps = get_wcaps(codec, nid);
|
||||||
|
unsigned int wid_type = get_wcaps_type(wid_caps);
|
||||||
|
|
||||||
if (pin_idx == pin_id)
|
if (wid_type != AC_WID_PIN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
|
if (nid == pin_nid)
|
||||||
AC_VERB_GET_CONNECT_SEL, 0);
|
continue;
|
||||||
|
|
||||||
/* Choose another unused converter */
|
curr = snd_hda_codec_read(codec, nid, 0,
|
||||||
if (curr == mux_id) {
|
AC_VERB_GET_CONNECT_SEL, 0);
|
||||||
err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx);
|
if (curr != mux_idx)
|
||||||
if (err < 0)
|
continue;
|
||||||
return;
|
|
||||||
snd_printdd("HDMI: choose converter %d for pin %d\n", mux_idx, pin_idx);
|
/* choose an unassigned converter. The conveters in the
|
||||||
snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
|
* connection list are in the same order as in the codec.
|
||||||
|
*/
|
||||||
|
for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
|
||||||
|
per_cvt = get_cvt(spec, cvt_idx);
|
||||||
|
if (!per_cvt->assigned) {
|
||||||
|
snd_printdd("choose cvt %d for pin nid %d\n",
|
||||||
|
cvt_idx, nid);
|
||||||
|
snd_hda_codec_write_cache(codec, nid, 0,
|
||||||
AC_VERB_SET_CONNECT_SEL,
|
AC_VERB_SET_CONNECT_SEL,
|
||||||
mux_idx);
|
cvt_idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1227,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
|
||||||
|
|
||||||
/* configure unused pins to choose other converters */
|
/* configure unused pins to choose other converters */
|
||||||
if (is_haswell(codec))
|
if (is_haswell(codec))
|
||||||
haswell_config_cvts(codec, pin_idx, mux_idx);
|
haswell_config_cvts(codec, per_pin->pin_nid, mux_idx);
|
||||||
|
|
||||||
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
|
snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
|
||||||
|
|
||||||
|
|
|
@ -3439,6 +3439,9 @@ static void alc283_fixup_chromebook(struct hda_codec *codec,
|
||||||
/* Set to manual mode */
|
/* Set to manual mode */
|
||||||
val = alc_read_coef_idx(codec, 0x06);
|
val = alc_read_coef_idx(codec, 0x06);
|
||||||
alc_write_coef_idx(codec, 0x06, val & ~0x000c);
|
alc_write_coef_idx(codec, 0x06, val & ~0x000c);
|
||||||
|
/* Enable Line1 input control by verb */
|
||||||
|
val = alc_read_coef_idx(codec, 0x1a);
|
||||||
|
alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3531,6 +3534,7 @@ enum {
|
||||||
ALC269VB_FIXUP_ORDISSIMO_EVE2,
|
ALC269VB_FIXUP_ORDISSIMO_EVE2,
|
||||||
ALC283_FIXUP_CHROME_BOOK,
|
ALC283_FIXUP_CHROME_BOOK,
|
||||||
ALC282_FIXUP_ASUS_TX300,
|
ALC282_FIXUP_ASUS_TX300,
|
||||||
|
ALC283_FIXUP_INT_MIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct hda_fixup alc269_fixups[] = {
|
static const struct hda_fixup alc269_fixups[] = {
|
||||||
|
@ -3790,6 +3794,16 @@ static const struct hda_fixup alc269_fixups[] = {
|
||||||
.type = HDA_FIXUP_FUNC,
|
.type = HDA_FIXUP_FUNC,
|
||||||
.v.func = alc282_fixup_asus_tx300,
|
.v.func = alc282_fixup_asus_tx300,
|
||||||
},
|
},
|
||||||
|
[ALC283_FIXUP_INT_MIC] = {
|
||||||
|
.type = HDA_FIXUP_VERBS,
|
||||||
|
.v.verbs = (const struct hda_verb[]) {
|
||||||
|
{0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
|
||||||
|
{0x20, AC_VERB_SET_PROC_COEF, 0x0011},
|
||||||
|
{ }
|
||||||
|
},
|
||||||
|
.chained = true,
|
||||||
|
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
|
@ -3874,7 +3888,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
||||||
SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
|
||||||
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
|
||||||
|
|
Loading…
Reference in a new issue