diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 32b0415..4ceb65a 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -128,6 +128,25 @@ SND_SOC_DPM_MIC("Mic1 Jack"),
 SND_SOC_DPM_AMP("Ext Amp", external_amp_event),
 };
 
+int corgi_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int mask = kcontrol->private_value;
+	
+	//ucontrol->value.integer.value[0] = corgi do something
+}
+
+int corgi_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int mask = kcontrol->private_value;
+	int val;
+	
+	val = (ucontrol->value.integer.value[0] & mask);
+	
+	/* do something with val */
+}
+
 /* example machine interconnections */
 static const char* intercon[][3] = {
 	
@@ -164,6 +183,7 @@ static const struct soc_enum wm8753_enum
 static const snd_kcontrol_new_t wm8753_mainstone_controls[] = {
 	SOC_SINGLE("Headphone Detect Switch", WM8753_OUTCTL, 6, 1, 0),
 	SOC_ENUM("Headphone Detect Polarity", wm8753_enum),
+	SOC_SINGLE_EXT("corgi bark switch", 1, corgi_get_volsw, corgi_put_volsw);
 };
 
 /*
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index cfd09ff..22e6af0 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -803,6 +803,32 @@ int snd_soc_put_enum_double(snd_kcontrol
 	return snd_soc_update_bits(codec, e->reg, mask, val);
 }
 
+/* ext volume and switch controls */
+int snd_soc_info_enum_ext(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = e->mask;
+	
+	if (uinfo->value.enumerated.item > e->mask - 1)
+		uinfo->value.enumerated.item = e->mask - 1;
+	strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+int snd_soc_info_volsw_ext(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	int mask = kcontrol->private_value;
+
+	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = mask;
+	return 0;
+}
+
 /* volume and switch controls */
 int snd_soc_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
@@ -868,9 +894,11 @@ int snd_soc_put_volsw(snd_kcontrol_t * k
 EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hw);
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
+EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
 EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
 EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
 EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
 EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
 EXPORT_SYMBOL_GPL(snd_soc_update_bits);
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 1d77745..babfcf0 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -41,12 +41,21 @@
   .mask = xmask, .texts = xtexts }
 #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
 	SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
+#define SOC_ENUM_SINGLE_EXT(xmask, xtexts) \
+{ .mask = xmask, .texts = xtexts }
 #define SOC_ENUM(xname, xenum) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_soc_info_enum_double, \
   .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
   .private_value = (unsigned long)&xenum }
-
- 
+#define SOC_SINGLE_EXT(xname, xmask, xhandler_get, xhandler_put) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_soc_info_volsw_ext, \
+  .get = xhandler_get, .put = xhandler_put, \
+  .private_value =  mask }
+#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_soc_info_enum_ext, \
+  .get = xhandler_get, .put = xhandler_put, \
+  .private_value = (unsigned long)&xenum }
+  
 /*
  * Audio interface types
  */
@@ -145,9 +154,11 @@ snd_kcontrol_t *snd_soc_cnew(const snd_k
 	void *data, char *long_name);
 
 int snd_soc_info_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo);
+int snd_soc_info_enum_ext(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_soc_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
+int snd_soc_info_volsw_ext(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_soc_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_soc_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 	

