Commit 8de4e5a6 authored by Lucas Tanure's avatar Lucas Tanure Committed by Takashi Iwai

ALSA: hda/cs8409: Avoid re-setting the same page as the last access

Signed-off-by: default avatarLucas Tanure <tanureal@opensource.cirrus.com>
Signed-off-by: default avatarVitaly Rodionov <vitalyr@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20210811185654.6837-16-vitalyr@opensource.cirrus.comSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent d395fd78
...@@ -170,18 +170,37 @@ static void cs8409_set_i2c_dev_addr(struct hda_codec *codec, unsigned int addr) ...@@ -170,18 +170,37 @@ static void cs8409_set_i2c_dev_addr(struct hda_codec *codec, unsigned int addr)
} }
} }
/**
* cs8409_i2c_set_page - CS8409 I2C set page register.
* @codec: the codec instance
* @i2c_reg: Page register
*
* Returns negative on error.
*/
static int cs8409_i2c_set_page(struct hda_codec *codec, unsigned int i2c_reg)
{
struct cs8409_spec *spec = codec->spec;
if (spec->paged && (spec->last_page != (i2c_reg >> 8))) {
cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8);
if (cs8409_i2c_wait_complete(codec) < 0)
return -EIO;
spec->last_page = i2c_reg >> 8;
}
return 0;
}
/** /**
* cs8409_i2c_read - CS8409 I2C Read. * cs8409_i2c_read - CS8409 I2C Read.
* @codec: the codec instance * @codec: the codec instance
* @i2c_address: I2C Address * @i2c_address: I2C Address
* @i2c_reg: Register to read * @i2c_reg: Register to read
* @paged: Is a paged transaction
* *
* CS8409 I2C Read. * CS8409 I2C Read.
* Returns negative on error, otherwise returns read value in bits 0-7. * Returns negative on error, otherwise returns read value in bits 0-7.
*/ */
static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, unsigned int i2c_reg, static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, unsigned int i2c_reg)
unsigned int paged)
{ {
struct cs8409_spec *spec = codec->spec; struct cs8409_spec *spec = codec->spec;
unsigned int i2c_reg_data; unsigned int i2c_reg_data;
...@@ -193,13 +212,10 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un ...@@ -193,13 +212,10 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un
cs8409_enable_i2c_clock(codec); cs8409_enable_i2c_clock(codec);
cs8409_set_i2c_dev_addr(codec, i2c_address); cs8409_set_i2c_dev_addr(codec, i2c_address);
if (paged) { if (cs8409_i2c_set_page(codec, i2c_reg)) {
cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8); codec_err(codec, "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
if (cs8409_i2c_wait_complete(codec) < 0) { __func__, i2c_address, i2c_reg);
codec_err(codec, "%s() Paged Transaction Failed 0x%02x : 0x%04x\n", return -EIO;
__func__, i2c_address, i2c_reg);
return -EIO;
}
} }
i2c_reg_data = (i2c_reg << 8) & 0x0ffff; i2c_reg_data = (i2c_reg << 8) & 0x0ffff;
...@@ -222,13 +238,12 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un ...@@ -222,13 +238,12 @@ static int cs8409_i2c_read(struct hda_codec *codec, unsigned int i2c_address, un
* @i2c_address: I2C Address * @i2c_address: I2C Address
* @i2c_reg: Register to write to * @i2c_reg: Register to write to
* @i2c_data: Data to write * @i2c_data: Data to write
* @paged: Is a paged transaction
* *
* CS8409 I2C Write. * CS8409 I2C Write.
* Returns negative on error, otherwise returns 0. * Returns negative on error, otherwise returns 0.
*/ */
static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, unsigned int i2c_reg, static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, unsigned int i2c_reg,
unsigned int i2c_data, unsigned int paged) unsigned int i2c_data)
{ {
struct cs8409_spec *spec = codec->spec; struct cs8409_spec *spec = codec->spec;
unsigned int i2c_reg_data; unsigned int i2c_reg_data;
...@@ -239,13 +254,10 @@ static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, u ...@@ -239,13 +254,10 @@ static int cs8409_i2c_write(struct hda_codec *codec, unsigned int i2c_address, u
cs8409_enable_i2c_clock(codec); cs8409_enable_i2c_clock(codec);
cs8409_set_i2c_dev_addr(codec, i2c_address); cs8409_set_i2c_dev_addr(codec, i2c_address);
if (paged) { if (cs8409_i2c_set_page(codec, i2c_reg)) {
cs8409_vendor_coef_set(codec, CS8409_I2C_QWRITE, i2c_reg >> 8); codec_err(codec, "%s() Paged Transaction Failed 0x%02x : 0x%04x\n",
if (cs8409_i2c_wait_complete(codec) < 0) { __func__, i2c_address, i2c_reg);
codec_err(codec, "%s() Paged Transaction Failed 0x%02x : 0x%04x\n", return -EIO;
__func__, i2c_address, i2c_reg);
return -EIO;
}
} }
i2c_reg_data = ((i2c_reg << 8) & 0x0ff00) | (i2c_data & 0x0ff); i2c_reg_data = ((i2c_reg << 8) & 0x0ff00) | (i2c_data & 0x0ff);
...@@ -325,14 +337,14 @@ int cs8409_cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_va ...@@ -325,14 +337,14 @@ int cs8409_cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_va
if (chs & BIT(0)) { if (chs & BIT(0)) {
spec->vol[ofs] = *valp; spec->vol[ofs] = *valp;
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHA, cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHA,
-(spec->vol[ofs]) & CS8409_CS42L42_REG_HS_VOL_MASK, 1); -(spec->vol[ofs]) & CS8409_CS42L42_REG_HS_VOL_MASK);
} }
if (chs & BIT(1)) { if (chs & BIT(1)) {
ofs++; ofs++;
valp++; valp++;
spec->vol[ofs] = *valp; spec->vol[ofs] = *valp;
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHB, cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHB,
-(spec->vol[ofs]) & CS8409_CS42L42_REG_HS_VOL_MASK, 1); -(spec->vol[ofs]) & CS8409_CS42L42_REG_HS_VOL_MASK);
} }
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
break; break;
...@@ -341,7 +353,7 @@ int cs8409_cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_va ...@@ -341,7 +353,7 @@ int cs8409_cs42l42_volume_put(struct snd_kcontrol *kctrl, struct snd_ctl_elem_va
if (chs & BIT(0)) { if (chs & BIT(0)) {
spec->vol[ofs] = *valp; spec->vol[ofs] = *valp;
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_AMIC_VOL, cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_AMIC_VOL,
spec->vol[ofs] & CS8409_CS42L42_REG_AMIC_VOL_MASK, 1); spec->vol[ofs] & CS8409_CS42L42_REG_AMIC_VOL_MASK);
} }
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
break; break;
...@@ -367,14 +379,15 @@ static void cs8409_cs42l42_reset(struct hda_codec *codec) ...@@ -367,14 +379,15 @@ static void cs8409_cs42l42_reset(struct hda_codec *codec)
usleep_range(10000, 15000); usleep_range(10000, 15000);
spec->cs42l42_suspended = 0; spec->cs42l42_suspended = 0;
spec->last_page = 0;
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
/* Clear interrupts, by reading interrupt status registers */ /* Clear interrupts, by reading interrupt status registers */
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308);
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1309, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1309);
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130A, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130A);
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130F, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130F);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
...@@ -391,20 +404,20 @@ static void cs8409_cs42l42_enable_jack_detect(struct hda_codec *codec) ...@@ -391,20 +404,20 @@ static void cs8409_cs42l42_enable_jack_detect(struct hda_codec *codec)
* Additionally set HSBIAS_SENSE_EN for some variants. * Additionally set HSBIAS_SENSE_EN for some variants.
*/ */
if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_BULLSEYE) if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_BULLSEYE)
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x0020);
else else
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x00a0, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b70, 0x00a0);
/* Clear WAKE# */ /* Clear WAKE# */
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x00C1, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x00C1);
/* Wait ~2.5ms */ /* Wait ~2.5ms */
usleep_range(2500, 3000); usleep_range(2500, 3000);
/* Set mode WAKE# output follows the combination logic directly */ /* Set mode WAKE# output follows the combination logic directly */
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x00C0, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b71, 0x00C0);
/* Clear interrupts status */ /* Clear interrupts status */
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f);
/* Enable interrupt */ /* Enable interrupt */
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
} }
...@@ -417,20 +430,20 @@ static void cs8409_cs42l42_run_jack_detect(struct hda_codec *codec) ...@@ -417,20 +430,20 @@ static void cs8409_cs42l42_run_jack_detect(struct hda_codec *codec)
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
/* Clear interrupts */ /* Clear interrupts */
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308);
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1b77);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xFF, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xFF);
cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1); cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1102, 0x87);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1f06, 0x86, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1f06, 0x86);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b74, 0x07, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1b74, 0x07);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0xFD, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0xFD);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0x80, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0x80);
/* Wait ~110ms*/ /* Wait ~110ms*/
usleep_range(110000, 200000); usleep_range(110000, 200000);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x111f, 0x77);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1120, 0xc0);
/* Wait ~10ms */ /* Wait ~10ms */
usleep_range(10000, 25000); usleep_range(10000, 25000);
...@@ -446,7 +459,7 @@ static void cs8409_cs42l42_reg_setup(struct hda_codec *codec) ...@@ -446,7 +459,7 @@ static void cs8409_cs42l42_reg_setup(struct hda_codec *codec)
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
for (; seq->addr; seq++) for (; seq->addr; seq++)
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, seq->addr, seq->reg, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, seq->addr, seq->reg);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
...@@ -480,9 +493,9 @@ static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -480,9 +493,9 @@ static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res)
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
/* Read jack detect status registers */ /* Read jack detect status registers */
reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308, 1); reg_cdc_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1308);
reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124, 1); reg_hs_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x1124);
reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f, 1); reg_ts_status = cs8409_i2c_read(codec, CS42L42_I2C_ADDR, 0x130f);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
...@@ -495,7 +508,7 @@ static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -495,7 +508,7 @@ static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res)
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
/* Disable HSDET_AUTO_DONE */ /* Disable HSDET_AUTO_DONE */
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0xFF, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x131b, 0xFF);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1); type = ((reg_hs_status & CS42L42_HSTYPE_MASK) + 1);
...@@ -522,7 +535,7 @@ static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -522,7 +535,7 @@ static void cs8409_jack_unsol_event(struct hda_codec *codec, unsigned int res)
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
/* Re-Enable Tip Sense Interrupt */ /* Re-Enable Tip Sense Interrupt */
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1320, 0xF3);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
} else { } else {
...@@ -589,7 +602,7 @@ static int cs8409_suspend(struct hda_codec *codec) ...@@ -589,7 +602,7 @@ static int cs8409_suspend(struct hda_codec *codec)
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
/* Power down CS42L42 ASP/EQ/MIX/HP */ /* Power down CS42L42 ASP/EQ/MIX/HP */
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x1101, 0xfe);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
spec->cs42l42_suspended = 1; spec->cs42l42_suspended = 1;
...@@ -652,7 +665,7 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec) ...@@ -652,7 +665,7 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG) { if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG) {
/* FULL_SCALE_VOL = 0 for Warlock / Cyborg */ /* FULL_SCALE_VOL = 0 for Warlock / Cyborg */
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01, 1); cs8409_i2c_write(codec, CS42L42_I2C_ADDR, 0x2001, 0x01);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
/* DMIC1_MO=00b, DMIC1/2_SR=1 */ /* DMIC1_MO=00b, DMIC1/2_SR=1 */
cs8409_vendor_coef_set(codec, 0x09, 0x0003); cs8409_vendor_coef_set(codec, 0x09, 0x0003);
...@@ -661,11 +674,11 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec) ...@@ -661,11 +674,11 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
/* Restore Volumes after Resume */ /* Restore Volumes after Resume */
mutex_lock(&spec->cs8409_i2c_mux); mutex_lock(&spec->cs8409_i2c_mux);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHA, cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHA,
-(spec->vol[1]) & CS8409_CS42L42_REG_HS_VOL_MASK, 1); -(spec->vol[1]) & CS8409_CS42L42_REG_HS_VOL_MASK);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHB, cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_HS_VOL_CHB,
-(spec->vol[2]) & CS8409_CS42L42_REG_HS_VOL_MASK, 1); -(spec->vol[2]) & CS8409_CS42L42_REG_HS_VOL_MASK);
cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_AMIC_VOL, cs8409_i2c_write(codec, CS42L42_I2C_ADDR, CS8409_CS42L42_REG_AMIC_VOL,
spec->vol[0] & CS8409_CS42L42_REG_AMIC_VOL_MASK, 1); spec->vol[0] & CS8409_CS42L42_REG_AMIC_VOL_MASK);
mutex_unlock(&spec->cs8409_i2c_mux); mutex_unlock(&spec->cs8409_i2c_mux);
cs8409_cs42l42_enable_jack_detect(codec); cs8409_cs42l42_enable_jack_detect(codec);
...@@ -771,6 +784,7 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix, ...@@ -771,6 +784,7 @@ void cs8409_cs42l42_fixups(struct hda_codec *codec, const struct hda_fixup *fix,
spec->cs42l42_hp_jack_in = 0; spec->cs42l42_hp_jack_in = 0;
spec->cs42l42_mic_jack_in = 0; spec->cs42l42_mic_jack_in = 0;
spec->cs42l42_suspended = 1; spec->cs42l42_suspended = 1;
spec->paged = 1;
/* Basic initial sequence for specific hw configuration */ /* Basic initial sequence for specific hw configuration */
snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs); snd_hda_sequence_write(codec, cs8409_cs42l42_init_verbs);
......
...@@ -283,6 +283,8 @@ struct cs8409_spec { ...@@ -283,6 +283,8 @@ struct cs8409_spec {
unsigned int i2c_clck_enabled; unsigned int i2c_clck_enabled;
unsigned int dev_addr; unsigned int dev_addr;
struct delayed_work i2c_clk_work; struct delayed_work i2c_clk_work;
unsigned int paged;
unsigned int last_page;
/* verb exec op override */ /* verb exec op override */
int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags, int (*exec_verb)(struct hdac_device *dev, unsigned int cmd, unsigned int flags,
......
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