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

Reply via email to