Pointed out by Arjan, the variable `pb_on` could be out-of-sync when it's not pretected well.
Add a mutex lock to serialize three functions: nc_power_up_pb, nc_power_down_pb and nc_set_selected_output_dev. Therefore, there will be no conflicts with the read and write of pb_on variable. Signed-off-by: Lu Guanqun <[email protected]> --- drivers/staging/intel_sst/intel_sst.h | 1 + drivers/staging/intel_sst/intelmid_v2_control.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/staging/intel_sst/intel_sst.h b/drivers/staging/intel_sst/intel_sst.h index 635cf58..4ad2829 100644 --- a/drivers/staging/intel_sst/intel_sst.h +++ b/drivers/staging/intel_sst/intel_sst.h @@ -84,6 +84,7 @@ struct snd_pmic_ops { int num_channel; int input_dev_id; int mute_status; + struct mutex lock; int pb_on, pbhs_on; int cap_on; int output_dev_id; diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c index 149a387..cd03f7c 100644 --- a/drivers/staging/intel_sst/intelmid_v2_control.c +++ b/drivers/staging/intel_sst/intelmid_v2_control.c @@ -131,6 +131,7 @@ static int nc_init_card(void) snd_pmic_ops_nc.master_mute = UNMUTE; snd_pmic_ops_nc.mute_status = UNMUTE; sst_sc_reg_access(sc_access, PMIC_WRITE, 27); + mutex_init(&snd_pmic_ops_nc.lock); pr_debug("sst: init complete!!\n"); return 0; } @@ -177,6 +178,7 @@ static int nc_power_up_pb(unsigned int port) return retval; if (port == 0xFF) return 0; + mutex_lock(&snd_pmic_ops_nc.lock); nc_enable_audiodac(MUTE); msleep(30); @@ -229,8 +231,9 @@ static int nc_power_up_pb(unsigned int port) if (snd_pmic_ops_nc.output_dev_id == MONO_EARPIECE || snd_pmic_ops_nc.output_dev_id == INTERNAL_SPKR) nc_set_amp_power(1); - return nc_enable_audiodac(UNMUTE); - + nc_enable_audiodac(UNMUTE); + mutex_unlock(&snd_pmic_ops_nc.lock); + return 0; } static int nc_power_up_cp(unsigned int port) @@ -351,7 +354,7 @@ static int nc_power_down_pb(unsigned int device) return retval; pr_debug("sst: powering dn pb....\n"); - + mutex_lock(&snd_pmic_ops_nc.lock); nc_enable_audiodac(MUTE); @@ -380,9 +383,9 @@ static int nc_power_down_pb(unsigned int device) snd_pmic_ops_nc.pb_on = 0; - return nc_enable_audiodac(UNMUTE); - - + nc_enable_audiodac(UNMUTE); + mutex_unlock(&snd_pmic_ops_nc.lock); + return 0; } static int nc_power_down_cp(unsigned int device) @@ -539,6 +542,7 @@ static int nc_set_selected_output_dev(u8 value) if (retval) return retval; pr_debug("sst: nc set selected output:%d\n", value); + mutex_lock(&snd_pmic_ops_nc.lock); switch (value) { case STEREO_HEADPHONE: if (snd_pmic_ops_nc.pb_on) { @@ -556,8 +560,10 @@ static int nc_set_selected_output_dev(u8 value) break; default: pr_err("sst: rcvd illegal request: %d\n", value); + mutex_unlock(&snd_pmic_ops_nc.lock); return -EINVAL; } + mutex_unlock(&snd_pmic_ops_nc.lock); return retval; } _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
