Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
8b940fc4
Commit
8b940fc4
authored
Nov 16, 2011
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix/hda' into topic/hda
parents
19723079
25d7d59d
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
107 additions
and
74 deletions
+107
-74
Documentation/sound/alsa/HD-Audio.txt
Documentation/sound/alsa/HD-Audio.txt
+4
-4
MAINTAINERS
MAINTAINERS
+1
-1
include/linux/mfd/wm8994/registers.h
include/linux/mfd/wm8994/registers.h
+15
-0
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_eld.c
+9
-4
sound/pci/hda/hda_local.h
sound/pci/hda/hda_local.h
+3
-0
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_hdmi.c
+33
-22
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_realtek.c
+1
-1
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_sigmatel.c
+9
-24
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.c
+29
-14
sound/usb/quirks.c
sound/usb/quirks.c
+3
-4
No files found.
Documentation/sound/alsa/HD-Audio.txt
View file @
8b940fc4
...
...
@@ -579,7 +579,7 @@ Development Tree
~~~~~~~~~~~~~~~~
The latest development codes for HD-audio are found on sound git tree:
- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
-2.6
.git
- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
The master branch or for-next branches can be used as the main
development branches in general while the HD-audio specific patches
...
...
@@ -594,7 +594,7 @@ is, installed via the usual spells: configure, make and make
install(-modules). See INSTALL in the package. The snapshot tarballs
are found at:
- ftp://ftp.
kernel.org/pub/linux/kernel
/people/tiwai/snapshot/
- ftp://ftp.
suse.com/pub
/people/tiwai/snapshot/
Sending a Bug Report
...
...
@@ -696,7 +696,7 @@ via hda-verb won't change the mixer value.
The hda-verb program is found in the ftp directory:
- ftp://ftp.
kernel.org/pub/linux/kernel
/people/tiwai/misc/
- ftp://ftp.
suse.com/pub
/people/tiwai/misc/
Also a git repository is available:
...
...
@@ -764,7 +764,7 @@ operation, the jack plugging simulation, etc.
The package is found in:
- ftp://ftp.
kernel.org/pub/linux/kernel
/people/tiwai/misc/
- ftp://ftp.
suse.com/pub
/people/tiwai/misc/
A git repository is available:
...
...
MAINTAINERS
View file @
8b940fc4
...
...
@@ -6122,7 +6122,7 @@ F: sound/
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
M: Liam Girdwood <lrg@ti.com>
M: Mark Brown <broonie@opensource.wolfsonmicro.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound
-2.6
.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://alsa-project.org/main/index.php/ASoC
S: Supported
...
...
include/linux/mfd/wm8994/registers.h
View file @
8b940fc4
...
...
@@ -1962,6 +1962,21 @@
#define WM8958_MICB2_DISCH_SHIFT 0
/* MICB2_DISCH */
#define WM8958_MICB2_DISCH_WIDTH 1
/* MICB2_DISCH */
/*
* R210 (0xD2) - Mic Detect 3
*/
#define WM8958_MICD_LVL_MASK 0x07FC
/* MICD_LVL - [10:2] */
#define WM8958_MICD_LVL_SHIFT 2
/* MICD_LVL - [10:2] */
#define WM8958_MICD_LVL_WIDTH 9
/* MICD_LVL - [10:2] */
#define WM8958_MICD_VALID 0x0002
/* MICD_VALID */
#define WM8958_MICD_VALID_MASK 0x0002
/* MICD_VALID */
#define WM8958_MICD_VALID_SHIFT 1
/* MICD_VALID */
#define WM8958_MICD_VALID_WIDTH 1
/* MICD_VALID */
#define WM8958_MICD_STS 0x0001
/* MICD_STS */
#define WM8958_MICD_STS_MASK 0x0001
/* MICD_STS */
#define WM8958_MICD_STS_SHIFT 0
/* MICD_STS */
#define WM8958_MICD_STS_WIDTH 1
/* MICD_STS */
/*
* R76 (0x4C) - Charge Pump (1)
*/
...
...
sound/pci/hda/hda_eld.c
View file @
8b940fc4
...
...
@@ -297,10 +297,18 @@ static int hdmi_update_eld(struct hdmi_eld *e,
buf
+
ELD_FIXED_BYTES
+
mnl
+
3
*
i
);
}
/*
* HDMI sink's ELD info cannot always be retrieved for now, e.g.
* in console or for audio devices. Assume the highest speakers
* configuration, to _not_ prohibit multi-channel audio playback.
*/
if
(
!
e
->
spk_alloc
)
e
->
spk_alloc
=
0xffff
;
e
->
eld_valid
=
true
;
return
0
;
out_fail:
e
->
eld_ver
=
0
;
return
-
EINVAL
;
}
...
...
@@ -323,9 +331,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
* ELD is valid, actual eld_size is assigned in hdmi_update_eld()
*/
if
(
!
eld
->
eld_valid
)
return
-
ENOENT
;
size
=
snd_hdmi_get_eld_size
(
codec
,
nid
);
if
(
size
==
0
)
{
/* wfg: workaround for ASUS P5E-VM HDMI board */
...
...
sound/pci/hda/hda_local.h
View file @
8b940fc4
...
...
@@ -653,6 +653,9 @@ struct hdmi_eld {
int
spk_alloc
;
int
sad_count
;
struct
cea_sad
sad
[
ELD_MAX_SAD
];
/*
* all fields above eld_buffer will be cleared before updating ELD
*/
char
eld_buffer
[
ELD_MAX_SIZE
];
#ifdef CONFIG_PROC_FS
struct
snd_info_entry
*
proc_entry
;
...
...
sound/pci/hda/patch_hdmi.c
View file @
8b940fc4
...
...
@@ -65,7 +65,10 @@ struct hdmi_spec_per_pin {
hda_nid_t
pin_nid
;
int
num_mux_nids
;
hda_nid_t
mux_nids
[
HDA_MAX_CONNECTIONS
];
struct
hda_codec
*
codec
;
struct
hdmi_eld
sink_eld
;
struct
delayed_work
work
;
};
struct
hdmi_spec
{
...
...
@@ -745,8 +748,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
* Unsolicited events
*/
static
void
hdmi_present_sense
(
struct
hda_codec
*
codec
,
hda_nid_t
pin_nid
,
struct
hdmi_eld
*
eld
);
static
void
hdmi_present_sense
(
struct
hdmi_spec_per_pin
*
per_pin
,
bool
retry
);
static
void
hdmi_intrinsic_event
(
struct
hda_codec
*
codec
,
unsigned
int
res
)
{
...
...
@@ -755,7 +757,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
int
pd
=
!!
(
res
&
AC_UNSOL_RES_PD
);
int
eldv
=
!!
(
res
&
AC_UNSOL_RES_ELDV
);
int
pin_idx
;
struct
hdmi_eld
*
eld
;
printk
(
KERN_INFO
"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d
\n
"
,
...
...
@@ -764,17 +765,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
pin_idx
=
pin_nid_to_pin_index
(
spec
,
pin_nid
);
if
(
pin_idx
<
0
)
return
;
eld
=
&
spec
->
pins
[
pin_idx
].
sink_eld
;
hdmi_present_sense
(
codec
,
pin_nid
,
eld
);
/*
* HDMI sink's ELD info cannot always be retrieved for now, e.g.
* in console or for audio devices. Assume the highest speakers
* configuration, to _not_ prohibit multi-channel audio playback.
*/
if
(
!
eld
->
spk_alloc
)
eld
->
spk_alloc
=
0xffff
;
hdmi_present_sense
(
&
spec
->
pins
[
pin_idx
],
true
);
}
static
void
hdmi_non_intrinsic_event
(
struct
hda_codec
*
codec
,
unsigned
int
res
)
...
...
@@ -968,9 +960,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
return
0
;
}
static
void
hdmi_present_sense
(
struct
hda_codec
*
codec
,
hda_nid_t
pin_nid
,
struct
hdmi_eld
*
eld
)
static
void
hdmi_present_sense
(
struct
hdmi_spec_per_pin
*
per_pin
,
bool
retry
)
{
struct
hda_codec
*
codec
=
per_pin
->
codec
;
struct
hdmi_eld
*
eld
=
&
per_pin
->
sink_eld
;
hda_nid_t
pin_nid
=
per_pin
->
pin_nid
;
/*
* Always execute a GetPinSense verb here, even when called from
* hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
...
...
@@ -980,26 +974,39 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
* the unsolicited response to avoid custom WARs.
*/
int
present
=
snd_hda_pin_sense
(
codec
,
pin_nid
);
bool
eld_valid
=
false
;
memset
(
eld
,
0
,
sizeof
(
*
eld
));
memset
(
eld
,
0
,
offsetof
(
struct
hdmi_eld
,
eld_buffer
));
eld
->
monitor_present
=
!!
(
present
&
AC_PINSENSE_PRESENCE
);
if
(
eld
->
monitor_present
)
eld
->
eld_valid
=
!!
(
present
&
AC_PINSENSE_ELDV
);
else
eld
->
eld_valid
=
0
;
eld_valid
=
!!
(
present
&
AC_PINSENSE_ELDV
);
printk
(
KERN_INFO
"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d
\n
"
,
codec
->
addr
,
pin_nid
,
eld
->
monitor_present
,
eld
->
eld
_valid
);
codec
->
addr
,
pin_nid
,
eld
->
monitor_present
,
eld_valid
);
if
(
eld
->
eld_valid
)
if
(
eld
_valid
)
{
if
(
!
snd_hdmi_get_eld
(
eld
,
codec
,
pin_nid
))
snd_hdmi_show_eld
(
eld
);
else
if
(
retry
)
{
queue_delayed_work
(
codec
->
bus
->
workq
,
&
per_pin
->
work
,
msecs_to_jiffies
(
300
));
}
}
snd_hda_input_jack_report
(
codec
,
pin_nid
);
}
static
void
hdmi_repoll_eld
(
struct
work_struct
*
work
)
{
struct
hdmi_spec_per_pin
*
per_pin
=
container_of
(
to_delayed_work
(
work
),
struct
hdmi_spec_per_pin
,
work
);
hdmi_present_sense
(
per_pin
,
false
);
}
static
int
hdmi_add_pin
(
struct
hda_codec
*
codec
,
hda_nid_t
pin_nid
)
{
struct
hdmi_spec
*
spec
=
codec
->
spec
;
...
...
@@ -1228,7 +1235,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
if
(
err
<
0
)
return
err
;
hdmi_present_sense
(
codec
,
per_pin
->
pin_nid
,
&
per_pin
->
sink_eld
);
hdmi_present_sense
(
per_pin
,
false
);
return
0
;
}
...
...
@@ -1279,6 +1286,8 @@ static int generic_hdmi_init(struct hda_codec *codec)
AC_VERB_SET_UNSOLICITED_ENABLE
,
AC_USRSP_EN
|
pin_nid
);
per_pin
->
codec
=
codec
;
INIT_DELAYED_WORK
(
&
per_pin
->
work
,
hdmi_repoll_eld
);
snd_hda_eld_proc_new
(
codec
,
eld
,
pin_idx
);
}
return
0
;
...
...
@@ -1293,10 +1302,12 @@ static void generic_hdmi_free(struct hda_codec *codec)
struct
hdmi_spec_per_pin
*
per_pin
=
&
spec
->
pins
[
pin_idx
];
struct
hdmi_eld
*
eld
=
&
per_pin
->
sink_eld
;
cancel_delayed_work
(
&
per_pin
->
work
);
snd_hda_eld_proc_free
(
codec
,
eld
);
}
snd_hda_input_jack_free
(
codec
);
flush_workqueue
(
codec
->
bus
->
workq
);
kfree
(
spec
);
}
...
...
sound/pci/hda/patch_realtek.c
View file @
8b940fc4
...
...
@@ -1472,7 +1472,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
switch
(
fix
->
type
)
{
case
ALC_FIXUP_SKU
:
if
(
action
!=
ALC_FIXUP_ACT_PRE_PROBE
||
!
fix
->
v
.
sku
)
break
;
;
break
;
snd_printdd
(
KERN_INFO
"hda_codec: %s: "
"Apply sku override for %s
\n
"
,
codec
->
chip_name
,
modelname
);
...
...
sound/pci/hda/patch_sigmatel.c
View file @
8b940fc4
...
...
@@ -227,7 +227,6 @@ struct sigmatel_spec {
/* power management */
unsigned
int
num_pwrs
;
const
unsigned
int
*
pwr_mapping
;
const
hda_nid_t
*
pwr_nids
;
const
hda_nid_t
*
dac_list
;
...
...
@@ -374,18 +373,15 @@ static const unsigned long stac92hd73xx_capvols[] = {
#define STAC92HD83_DAC_COUNT 3
static
const
hda_nid_t
stac92hd83xxx_pwr_nids
[
4
]
=
{
0xa
,
0xb
,
0xd
,
0xe
,
static
const
hda_nid_t
stac92hd83xxx_pwr_nids
[
7
]
=
{
0x0a
,
0x0b
,
0x0c
,
0xd
,
0x0e
,
0x0f
,
0x10
};
static
const
hda_nid_t
stac92hd83xxx_slave_dig_outs
[
2
]
=
{
0x1e
,
0
,
};
static
const
unsigned
int
stac92hd83xxx_pwr_mapping
[
4
]
=
{
0x03
,
0x0c
,
0x20
,
0x40
,
};
static
const
hda_nid_t
stac92hd83xxx_dmic_nids
[]
=
{
0x11
,
0x20
,
};
...
...
@@ -4470,8 +4466,12 @@ static int stac92xx_init(struct hda_codec *codec)
stac_toggle_power_map
(
codec
,
nid
,
1
);
continue
;
}
if
(
enable_pin_detect
(
codec
,
nid
,
STAC_PWR_EVENT
))
if
(
enable_pin_detect
(
codec
,
nid
,
STAC_PWR_EVENT
))
{
stac_issue_unsol_event
(
codec
,
nid
);
continue
;
}
/* none of the above, turn the port OFF */
stac_toggle_power_map
(
codec
,
nid
,
0
);
}
/* sync mute LED */
...
...
@@ -4727,11 +4727,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
if
(
idx
>=
spec
->
num_pwrs
)
return
;
/* several codecs have two power down bits */
if
(
spec
->
pwr_mapping
)
idx
=
spec
->
pwr_mapping
[
idx
];
else
idx
=
1
<<
idx
;
idx
=
1
<<
idx
;
val
=
snd_hda_codec_read
(
codec
,
codec
->
afg
,
0
,
0x0fec
,
0x0
)
&
0xff
;
if
(
enable
)
...
...
@@ -5629,9 +5625,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
snd_hda_codec_set_pincfg
(
codec
,
0xf
,
0x2181205e
);
}
/* reset pin power-down; Windows may leave these bits after reboot */
snd_hda_codec_write_cache
(
codec
,
codec
->
afg
,
0
,
0x7EC
,
0
);
snd_hda_codec_write_cache
(
codec
,
codec
->
afg
,
0
,
0x7ED
,
0
);
codec
->
no_trigger_sense
=
1
;
codec
->
spec
=
spec
;
...
...
@@ -5641,7 +5634,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
codec
->
slave_dig_outs
=
stac92hd83xxx_slave_dig_outs
;
spec
->
digbeep_nid
=
0x21
;
spec
->
pwr_nids
=
stac92hd83xxx_pwr_nids
;
spec
->
pwr_mapping
=
stac92hd83xxx_pwr_mapping
;
spec
->
num_pwrs
=
ARRAY_SIZE
(
stac92hd83xxx_pwr_nids
);
spec
->
multiout
.
dac_nids
=
spec
->
dac_nids
;
spec
->
init
=
stac92hd83xxx_core_init
;
...
...
@@ -5658,9 +5650,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
stac92xx_set_config_regs
(
codec
,
stac92hd83xxx_brd_tbl
[
spec
->
board_config
]);
if
(
spec
->
board_config
!=
STAC_92HD83XXX_PWR_REF
)
spec
->
num_pwrs
=
0
;
codec
->
patch_ops
=
stac92xx_patch_ops
;
if
(
find_mute_led_gpio
(
codec
,
0
))
...
...
@@ -5869,8 +5858,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
(
codec
->
revision_id
&
0xf
)
==
1
)
spec
->
stream_delay
=
40
;
/* 40 milliseconds */
/* no output amps */
spec
->
num_pwrs
=
0
;
/* disable VSW */
spec
->
init
=
stac92hd71bxx_core_init
;
unmute_init
++
;
...
...
@@ -5885,8 +5872,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
if
((
codec
->
revision_id
&
0xf
)
==
1
)
spec
->
stream_delay
=
40
;
/* 40 milliseconds */
/* no output amps */
spec
->
num_pwrs
=
0
;
/* fallthru */
default:
spec
->
init
=
stac92hd71bxx_core_init
;
...
...
sound/soc/codecs/wm8994.c
View file @
8b940fc4
...
...
@@ -56,7 +56,7 @@ static int wm8994_retune_mobile_base[] = {
static
int
wm8994_readable
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
struct
wm8994_priv
*
wm8994
=
snd_soc_codec_get_drvdata
(
codec
);
struct
wm8994
*
control
=
wm8994
->
control_data
;
struct
wm8994
*
control
=
codec
->
control_data
;
switch
(
reg
)
{
case
WM8994_GPIO_1
:
...
...
@@ -3030,19 +3030,34 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
{
struct
wm8994_priv
*
wm8994
=
data
;
struct
snd_soc_codec
*
codec
=
wm8994
->
codec
;
int
reg
;
int
reg
,
count
;
reg
=
snd_soc_read
(
codec
,
WM8958_MIC_DETECT_3
);
if
(
reg
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to read mic detect status: %d
\n
"
,
reg
);
return
IRQ_NONE
;
}
/* We may occasionally read a detection without an impedence
* range being provided - if that happens loop again.
*/
count
=
10
;
do
{
reg
=
snd_soc_read
(
codec
,
WM8958_MIC_DETECT_3
);
if
(
reg
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to read mic detect status: %d
\n
"
,
reg
);
return
IRQ_NONE
;
}
if
(
!
(
reg
&
WM8958_MICD_VALID
))
{
dev_dbg
(
codec
->
dev
,
"Mic detect data not valid
\n
"
);
goto
out
;
}
if
(
!
(
reg
&
WM8958_MICD_VALID
))
{
dev_dbg
(
codec
->
dev
,
"Mic detect data not valid
\n
"
);
goto
out
;
}
if
(
!
(
reg
&
WM8958_MICD_STS
)
||
(
reg
&
WM8958_MICD_LVL_MASK
))
break
;
msleep
(
1
);
}
while
(
count
--
);
if
(
count
==
0
)
dev_warn
(
codec
->
dev
,
"No impedence range reported for jack
\n
"
);
#ifndef CONFIG_SND_SOC_WM8994_MODULE
trace_snd_soc_jack_irq
(
dev_name
(
codec
->
dev
));
...
...
@@ -3180,9 +3195,9 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994_request_irq
(
codec
->
control_data
,
WM8994_IRQ_FIFOS_ERR
,
wm8994_fifo_error
,
"FIFO error"
,
codec
);
wm8994_request_irq
(
wm8994
->
control_data
,
WM8994_IRQ_TEMP_WARN
,
wm8994_request_irq
(
codec
->
control_data
,
WM8994_IRQ_TEMP_WARN
,
wm8994_temp_warn
,
"Thermal warning"
,
codec
);
wm8994_request_irq
(
wm8994
->
control_data
,
WM8994_IRQ_TEMP_SHUT
,
wm8994_request_irq
(
codec
->
control_data
,
WM8994_IRQ_TEMP_SHUT
,
wm8994_temp_shut
,
"Thermal shutdown"
,
codec
);
ret
=
wm8994_request_irq
(
codec
->
control_data
,
WM8994_IRQ_DCS_DONE
,
...
...
sound/usb/quirks.c
View file @
8b940fc4
...
...
@@ -137,12 +137,12 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
return
-
ENOMEM
;
}
if
(
fp
->
nr_rates
>
0
)
{
rate_table
=
kmalloc
(
sizeof
(
int
)
*
fp
->
nr_rates
,
GFP_KERNEL
);
rate_table
=
kmemdup
(
fp
->
rate_table
,
sizeof
(
int
)
*
fp
->
nr_rates
,
GFP_KERNEL
);
if
(
!
rate_table
)
{
kfree
(
fp
);
return
-
ENOMEM
;
}
memcpy
(
rate_table
,
fp
->
rate_table
,
sizeof
(
int
)
*
fp
->
nr_rates
);
fp
->
rate_table
=
rate_table
;
}
...
...
@@ -224,10 +224,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
if
(
altsd
->
bNumEndpoints
!=
1
)
return
-
ENXIO
;
fp
=
km
alloc
(
sizeof
(
*
fp
),
GFP_KERNEL
);
fp
=
km
emdup
(
&
ua_format
,
sizeof
(
*
fp
),
GFP_KERNEL
);
if
(
!
fp
)
return
-
ENOMEM
;
memcpy
(
fp
,
&
ua_format
,
sizeof
(
*
fp
));
fp
->
iface
=
altsd
->
bInterfaceNumber
;
fp
->
endpoint
=
get_endpoint
(
alts
,
0
)
->
bEndpointAddress
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment