Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
84a3bd06
Commit
84a3bd06
authored
Dec 12, 2009
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/hda' into for-linus
parents
f52d7a43
52dc4386
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
175 additions
and
57 deletions
+175
-57
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_codec.h
+5
-0
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_intel.c
+2
-1
sound/pci/hda/hda_proc.c
sound/pci/hda/hda_proc.c
+6
-1
sound/pci/hda/patch_intelhdmi.c
sound/pci/hda/patch_intelhdmi.c
+86
-28
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_sigmatel.c
+76
-27
No files found.
sound/pci/hda/hda_codec.h
View file @
84a3bd06
...
...
@@ -255,9 +255,13 @@ enum {
* in HD-audio specification
*/
#define AC_PINCAP_HDMI (1<<7)
/* HDMI pin */
#define AC_PINCAP_DP (1<<24)
/* DisplayPort pin, can
* coexist with AC_PINCAP_HDMI
*/
#define AC_PINCAP_VREF (0x37<<8)
#define AC_PINCAP_VREF_SHIFT 8
#define AC_PINCAP_EAPD (1<<16)
/* EAPD capable */
#define AC_PINCAP_HBR (1<<27)
/* High Bit Rate */
/* Vref status (used in pin cap) */
#define AC_PINCAP_VREF_HIZ (1<<0)
/* Hi-Z */
#define AC_PINCAP_VREF_50 (1<<1)
/* 50% */
...
...
@@ -635,6 +639,7 @@ struct hda_bus {
unsigned
int
rirb_error
:
1
;
/* error in codec communication */
unsigned
int
response_reset
:
1
;
/* controller was reset */
unsigned
int
in_reset
:
1
;
/* during reset operation */
unsigned
int
power_keep_link_on
:
1
;
/* don't power off HDA link */
};
/*
...
...
sound/pci/hda/hda_intel.c
View file @
84a3bd06
...
...
@@ -2082,7 +2082,8 @@ static void azx_power_notify(struct hda_bus *bus)
}
if
(
power_on
)
azx_init_chip
(
chip
);
else
if
(
chip
->
running
&&
power_save_controller
)
else
if
(
chip
->
running
&&
power_save_controller
&&
!
bus
->
power_keep_link_on
)
azx_stop_chip
(
chip
);
}
#endif
/* CONFIG_SND_HDA_POWER_SAVE */
...
...
sound/pci/hda/hda_proc.c
View file @
84a3bd06
...
...
@@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
/* Realtek uses this bit as a different meaning */
if
((
codec
->
vendor_id
>>
16
)
==
0x10ec
)
snd_iprintf
(
buffer
,
" R/L"
);
else
else
{
if
(
caps
&
AC_PINCAP_HBR
)
snd_iprintf
(
buffer
,
" HBR"
);
snd_iprintf
(
buffer
,
" HDMI"
);
}
}
if
(
caps
&
AC_PINCAP_DP
)
snd_iprintf
(
buffer
,
" DP"
);
if
(
caps
&
AC_PINCAP_TRIG_REQ
)
snd_iprintf
(
buffer
,
" Trigger"
);
if
(
caps
&
AC_PINCAP_IMP_SENSE
)
...
...
sound/pci/hda/patch_intelhdmi.c
View file @
84a3bd06
...
...
@@ -145,6 +145,42 @@ struct cea_channel_speaker_allocation {
int
spk_mask
;
};
/*
* ALSA sequence is:
*
* surround40 surround41 surround50 surround51 surround71
* ch0 front left = = = =
* ch1 front right = = = =
* ch2 rear left = = = =
* ch3 rear right = = = =
* ch4 LFE center center center
* ch5 LFE LFE
* ch6 side left
* ch7 side right
*
* surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
*/
static
int
hdmi_channel_mapping
[
0x32
][
8
]
=
{
/* stereo */
[
0x00
]
=
{
0x00
,
0x11
,
0xf2
,
0xf3
,
0xf4
,
0xf5
,
0xf6
,
0xf7
},
/* 2.1 */
[
0x01
]
=
{
0x00
,
0x11
,
0x22
,
0xf3
,
0xf4
,
0xf5
,
0xf6
,
0xf7
},
/* Dolby Surround */
[
0x02
]
=
{
0x00
,
0x11
,
0x23
,
0xf2
,
0xf4
,
0xf5
,
0xf6
,
0xf7
},
/* surround40 */
[
0x08
]
=
{
0x00
,
0x11
,
0x24
,
0x35
,
0xf3
,
0xf2
,
0xf6
,
0xf7
},
/* 4ch */
[
0x03
]
=
{
0x00
,
0x11
,
0x23
,
0x32
,
0x44
,
0xf5
,
0xf6
,
0xf7
},
/* surround41 */
[
0x09
]
=
{
0x00
,
0x11
,
0x24
,
0x34
,
0x43
,
0xf2
,
0xf6
,
0xf7
},
/* surround50 */
[
0x0a
]
=
{
0x00
,
0x11
,
0x24
,
0x35
,
0x43
,
0xf2
,
0xf6
,
0xf7
},
/* surround51 */
[
0x0b
]
=
{
0x00
,
0x11
,
0x24
,
0x35
,
0x43
,
0x52
,
0xf6
,
0xf7
},
/* 7.1 */
[
0x13
]
=
{
0x00
,
0x11
,
0x26
,
0x37
,
0x43
,
0x52
,
0x64
,
0x75
},
};
/*
* This is an ordered list!
*
...
...
@@ -152,32 +188,36 @@ struct cea_channel_speaker_allocation {
* hdmi_setup_channel_allocation().
*/
static
struct
cea_channel_speaker_allocation
channel_allocations
[]
=
{
/* channel:
8 7 6 5 4 3 2 1
*/
/* channel:
7 6 5 4 3 2 1 0
*/
{
.
ca_index
=
0x00
,
.
speakers
=
{
0
,
0
,
0
,
0
,
0
,
0
,
FR
,
FL
}
},
/* 2.1 */
{
.
ca_index
=
0x01
,
.
speakers
=
{
0
,
0
,
0
,
0
,
0
,
LFE
,
FR
,
FL
}
},
/* Dolby Surround */
{
.
ca_index
=
0x02
,
.
speakers
=
{
0
,
0
,
0
,
0
,
FC
,
0
,
FR
,
FL
}
},
/* surround40 */
{
.
ca_index
=
0x08
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
0
,
0
,
FR
,
FL
}
},
/* surround41 */
{
.
ca_index
=
0x09
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
0
,
LFE
,
FR
,
FL
}
},
/* surround50 */
{
.
ca_index
=
0x0a
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
FC
,
0
,
FR
,
FL
}
},
/* surround51 */
{
.
ca_index
=
0x0b
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
/* 6.1 */
{
.
ca_index
=
0x0f
,
.
speakers
=
{
0
,
RC
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
/* surround71 */
{
.
ca_index
=
0x13
,
.
speakers
=
{
RRC
,
RLC
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x03
,
.
speakers
=
{
0
,
0
,
0
,
0
,
FC
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x04
,
.
speakers
=
{
0
,
0
,
0
,
RC
,
0
,
0
,
FR
,
FL
}
},
{
.
ca_index
=
0x05
,
.
speakers
=
{
0
,
0
,
0
,
RC
,
0
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x06
,
.
speakers
=
{
0
,
0
,
0
,
RC
,
FC
,
0
,
FR
,
FL
}
},
{
.
ca_index
=
0x07
,
.
speakers
=
{
0
,
0
,
0
,
RC
,
FC
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x08
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
0
,
0
,
FR
,
FL
}
},
{
.
ca_index
=
0x09
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
0
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x0a
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
FC
,
0
,
FR
,
FL
}
},
/* 5.1 */
{
.
ca_index
=
0x0b
,
.
speakers
=
{
0
,
0
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x0c
,
.
speakers
=
{
0
,
RC
,
RR
,
RL
,
0
,
0
,
FR
,
FL
}
},
{
.
ca_index
=
0x0d
,
.
speakers
=
{
0
,
RC
,
RR
,
RL
,
0
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x0e
,
.
speakers
=
{
0
,
RC
,
RR
,
RL
,
FC
,
0
,
FR
,
FL
}
},
/* 6.1 */
{
.
ca_index
=
0x0f
,
.
speakers
=
{
0
,
RC
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x10
,
.
speakers
=
{
RRC
,
RLC
,
RR
,
RL
,
0
,
0
,
FR
,
FL
}
},
{
.
ca_index
=
0x11
,
.
speakers
=
{
RRC
,
RLC
,
RR
,
RL
,
0
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x12
,
.
speakers
=
{
RRC
,
RLC
,
RR
,
RL
,
FC
,
0
,
FR
,
FL
}
},
/* 7.1 */
{
.
ca_index
=
0x13
,
.
speakers
=
{
RRC
,
RLC
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x14
,
.
speakers
=
{
FRC
,
FLC
,
0
,
0
,
0
,
0
,
FR
,
FL
}
},
{
.
ca_index
=
0x15
,
.
speakers
=
{
FRC
,
FLC
,
0
,
0
,
0
,
LFE
,
FR
,
FL
}
},
{
.
ca_index
=
0x16
,
.
speakers
=
{
FRC
,
FLC
,
0
,
0
,
FC
,
0
,
FR
,
FL
}
},
...
...
@@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
{
.
ca_index
=
0x31
,
.
speakers
=
{
FRW
,
FLW
,
RR
,
RL
,
FC
,
LFE
,
FR
,
FL
}
},
};
/*
* HDA/HDMI auto parsing
*/
...
...
@@ -344,7 +383,7 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec)
break
;
case
AC_WID_PIN
:
caps
=
snd_hda_param_read
(
codec
,
nid
,
AC_PAR_PIN_CAP
);
if
(
!
(
caps
&
AC_PINCAP_HDMI
))
if
(
!
(
caps
&
(
AC_PINCAP_HDMI
|
AC_PINCAP_DP
)
))
continue
;
if
(
intel_hdmi_add_pin
(
codec
,
nid
)
<
0
)
return
-
EINVAL
;
...
...
@@ -352,6 +391,17 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec)
}
}
/*
* G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
* can be lost and presence sense verb will become inaccurate if the
* HDA link is powered off at hot plug or hw initialization time.
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE
if
(
!
(
snd_hda_param_read
(
codec
,
codec
->
afg
,
AC_PAR_POWER_STATE
)
&
AC_PWRST_EPSS
))
codec
->
bus
->
power_keep_link_on
=
1
;
#endif
return
0
;
}
...
...
@@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec,
AC_VERB_SET_CVT_CHAN_COUNT
,
chs
-
1
);
}
static
void
hdmi_debug_channel_mapping
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
)
static
void
hdmi_debug_channel_mapping
(
struct
hda_codec
*
codec
,
hda_nid_t
pin_nid
)
{
#ifdef CONFIG_SND_DEBUG_VERBOSE
int
i
;
int
slot
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
slot
=
snd_hda_codec_read
(
codec
,
nid
,
0
,
slot
=
snd_hda_codec_read
(
codec
,
pin_
nid
,
0
,
AC_VERB_GET_HDMI_CHAN_SLOT
,
i
);
printk
(
KERN_DEBUG
"HDMI: ASP channel %d => slot %d
\n
"
,
slot
>>
4
,
slot
&
0xf
);
...
...
@@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
return
ai
->
CA
;
}
static
void
hdmi_setup_channel_mapping
(
struct
hda_codec
*
codec
,
hda_nid_t
nid
,
static
void
hdmi_setup_channel_mapping
(
struct
hda_codec
*
codec
,
hda_nid_t
pin_nid
,
struct
hdmi_audio_infoframe
*
ai
)
{
int
i
;
int
ca
=
ai
->
CA
;
int
err
;
if
(
!
ai
->
CA
)
return
;
/*
* TODO: adjust channel mapping if necessary
* ALSA sequence is front/surr/clfe/side?
*/
if
(
hdmi_channel_mapping
[
ca
][
1
]
==
0
)
{
for
(
i
=
0
;
i
<
channel_allocations
[
ca
].
channels
;
i
++
)
hdmi_channel_mapping
[
ca
][
i
]
=
i
|
(
i
<<
4
);
for
(;
i
<
8
;
i
++
)
hdmi_channel_mapping
[
ca
][
i
]
=
0xf
|
(
i
<<
4
);
}
for
(
i
=
0
;
i
<
8
;
i
++
)
snd_hda_codec_write
(
codec
,
nid
,
0
,
AC_VERB_SET_HDMI_CHAN_SLOT
,
(
i
<<
4
)
|
i
);
for
(
i
=
0
;
i
<
8
;
i
++
)
{
err
=
snd_hda_codec_write
(
codec
,
pin_nid
,
0
,
AC_VERB_SET_HDMI_CHAN_SLOT
,
hdmi_channel_mapping
[
ca
][
i
]);
if
(
err
)
{
snd_printdd
(
KERN_INFO
"HDMI: channel mapping failed
\n
"
);
break
;
}
}
hdmi_debug_channel_mapping
(
codec
,
nid
);
hdmi_debug_channel_mapping
(
codec
,
pin_
nid
);
}
static
bool
hdmi_infoframe_uptodate
(
struct
hda_codec
*
codec
,
hda_nid_t
pin_nid
,
...
...
@@ -676,7 +734,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
};
hdmi_setup_channel_allocation
(
codec
,
nid
,
&
ai
);
hdmi_setup_channel_mapping
(
codec
,
nid
,
&
ai
);
for
(
i
=
0
;
i
<
spec
->
num_pins
;
i
++
)
{
if
(
spec
->
pin_cvt
[
i
]
!=
nid
)
...
...
@@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
pin_nid
=
spec
->
pin
[
i
];
if
(
!
hdmi_infoframe_uptodate
(
codec
,
pin_nid
,
&
ai
))
{
hdmi_setup_channel_mapping
(
codec
,
pin_nid
,
&
ai
);
hdmi_stop_infoframe_trans
(
codec
,
pin_nid
);
hdmi_fill_audio_infoframe
(
codec
,
pin_nid
,
&
ai
);
hdmi_start_infoframe_trans
(
codec
,
pin_nid
);
...
...
sound/pci/hda/patch_sigmatel.c
View file @
84a3bd06
...
...
@@ -209,6 +209,7 @@ struct sigmatel_spec {
unsigned
int
gpio_data
;
unsigned
int
gpio_mute
;
unsigned
int
gpio_led
;
unsigned
int
gpio_led_polarity
;
/* stream */
unsigned
int
stream_delay
;
...
...
@@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = {
0x904601b0
,
};
static
unsigned
int
intel_dg45id_pin_configs
[
14
]
=
{
0x02214230
,
0x02A19240
,
0x01013214
,
0x01014210
,
0x01A19250
,
0x01011212
,
0x01016211
,
0x40f000f0
,
0x40f000f0
,
0x40f000f0
,
0x40f000f0
,
0x014510A0
,
0x074510B0
,
0x40f000f0
};
static
unsigned
int
*
stac92hd73xx_brd_tbl
[
STAC_92HD73XX_MODELS
]
=
{
[
STAC_92HD73XX_REF
]
=
ref92hd73xx_pin_configs
,
[
STAC_DELL_M6_AMIC
]
=
dell_m6_pin_configs
,
...
...
@@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
[
STAC_DELL_M6_BOTH
]
=
dell_m6_pin_configs
,
[
STAC_DELL_EQ
]
=
dell_m6_pin_configs
,
[
STAC_ALIENWARE_M17X
]
=
alienware_m17x_pin_configs
,
[
STAC_92HD73XX_INTEL
]
=
intel_dg45id_pin_configs
,
};
static
const
char
*
stac92hd73xx_models
[
STAC_92HD73XX_MODELS
]
=
{
...
...
@@ -4724,13 +4733,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
}
}
static
int
hp_bseries_system
(
u32
subsystem_id
)
/*
* This method searches for the mute LED GPIO configuration
* provided as OEM string in SMBIOS. The format of that string
* is HP_Mute_LED_P_G or HP_Mute_LED_P
* where P can be 0 or 1 and defines mute LED GPIO control state (low/high)
* that corresponds to the NOT muted state of the master volume
* and G is the index of the GPIO to use as the mute LED control (0..9)
* If _G portion is missing it is assigned based on the codec ID
*
* So, HP B-series like systems may have HP_Mute_LED_0 (current models)
* or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings
*/
static
int
find_mute_led_gpio
(
struct
hda_codec
*
codec
)
{
struct
sigmatel_spec
*
spec
=
codec
->
spec
;
const
struct
dmi_device
*
dev
=
NULL
;
if
((
codec
->
subsystem_id
>>
16
)
==
PCI_VENDOR_ID_HP
)
{
while
((
dev
=
dmi_find_device
(
DMI_DEV_TYPE_OEM_STRING
,
NULL
,
dev
)))
{
if
(
sscanf
(
dev
->
name
,
"HP_Mute_LED_%d_%d"
,
&
spec
->
gpio_led_polarity
,
&
spec
->
gpio_led
)
==
2
)
{
spec
->
gpio_led
=
1
<<
spec
->
gpio_led
;
return
1
;
}
if
(
sscanf
(
dev
->
name
,
"HP_Mute_LED_%d"
,
&
spec
->
gpio_led_polarity
)
==
1
)
{
switch
(
codec
->
vendor_id
)
{
case
0x111d7608
:
/* GPIO 0 */
spec
->
gpio_led
=
0x01
;
return
1
;
case
0x111d7600
:
case
0x111d7601
:
case
0x111d7602
:
case
0x111d7603
:
/* GPIO 3 */
spec
->
gpio_led
=
0x08
;
return
1
;
}
}
}
}
return
0
;
}
static
int
hp_blike_system
(
u32
subsystem_id
)
{
switch
(
subsystem_id
)
{
case
0x103c307e
:
case
0x103c307f
:
case
0x103c3080
:
case
0x103c3081
:
case
0x103c1520
:
case
0x103c1521
:
case
0x103c1523
:
case
0x103c1524
:
case
0x103c1525
:
case
0x103c1722
:
case
0x103c1723
:
case
0x103c1724
:
...
...
@@ -4739,6 +4796,14 @@ static int hp_bseries_system(u32 subsystem_id)
case
0x103c1727
:
case
0x103c1728
:
case
0x103c1729
:
case
0x103c172a
:
case
0x103c172b
:
case
0x103c307e
:
case
0x103c307f
:
case
0x103c3080
:
case
0x103c3081
:
case
0x103c7007
:
case
0x103c7008
:
return
1
;
}
return
0
;
...
...
@@ -4833,7 +4898,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
else
spec
->
gpio_data
|=
spec
->
gpio_led
;
/* white */
if
(
hp_bseries_system
(
codec
->
subsystem_id
)
)
{
if
(
!
spec
->
gpio_led_polarity
)
{
/* LED state is inverted on these systems */
spec
->
gpio_data
^=
spec
->
gpio_led
;
}
...
...
@@ -5526,7 +5591,7 @@ again:
break
;
}
if
(
hp_b
series
_system
(
codec
->
subsystem_id
))
{
if
(
hp_b
like
_system
(
codec
->
subsystem_id
))
{
pin_cfg
=
snd_hda_codec_get_pincfg
(
codec
,
0x0f
);
if
(
get_defcfg_device
(
pin_cfg
)
==
AC_JACK_LINE_OUT
||
get_defcfg_device
(
pin_cfg
)
==
AC_JACK_SPEAKER
||
...
...
@@ -5544,26 +5609,10 @@ again:
}
}
if
((
codec
->
subsystem_id
>>
16
)
==
PCI_VENDOR_ID_HP
)
{
const
struct
dmi_device
*
dev
=
NULL
;
while
((
dev
=
dmi_find_device
(
DMI_DEV_TYPE_OEM_STRING
,
NULL
,
dev
)))
{
if
(
strcmp
(
dev
->
name
,
"HP_Mute_LED_1"
))
{
switch
(
codec
->
vendor_id
)
{
case
0x111d7608
:
spec
->
gpio_led
=
0x01
;
break
;
case
0x111d7600
:
case
0x111d7601
:
case
0x111d7602
:
case
0x111d7603
:
spec
->
gpio_led
=
0x08
;
break
;
}
break
;
}
}
}
if
(
find_mute_led_gpio
(
codec
))
snd_printd
(
"mute LED gpio %d polarity %d
\n
"
,
spec
->
gpio_led
,
spec
->
gpio_led_polarity
);
#ifdef CONFIG_SND_HDA_POWER_SAVE
if
(
spec
->
gpio_led
)
{
...
...
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