diff --git a/VersionNum b/VersionNum
index 622538e5f1e391680e8325beac2c64d0d5b128b7..0299445c853487192175a848b0e6e628975f17bd 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,23 @@
-/* (2.03)
+/* (2.04)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
  * Last processed by srccommit version: 1.1.
  *
  */
-#define Module_MajorVersion_CMHG        2.03
+#define Module_MajorVersion_CMHG        2.04
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                14 Jan 2012
+#define Module_Date_CMHG                21 Jan 2012
 
-#define Module_MajorVersion             "2.03"
-#define Module_Version                  203
+#define Module_MajorVersion             "2.04"
+#define Module_Version                  204
 #define Module_MinorVersion             ""
-#define Module_Date                     "14 Jan 2012"
+#define Module_Date                     "21 Jan 2012"
 
-#define Module_ApplicationDate          "14-Jan-12"
+#define Module_ApplicationDate          "21-Jan-12"
 
 #define Module_ComponentName            "SndSetup"
 #define Module_ComponentPath            "castle/RiscOS/Sources/SystemRes/Configure2/PlugIns/SndSetup"
 
-#define Module_FullVersion              "2.03"
-#define Module_HelpVersion              "2.03 (14 Jan 2012)"
-#define Module_LibraryVersionInfo       "2:3"
+#define Module_FullVersion              "2.04"
+#define Module_HelpVersion              "2.04 (21 Jan 2012)"
+#define Module_LibraryVersionInfo       "2:4"
diff --git a/c/main b/c/main
index 85af95063d944fd83dc459c4b82c315f6e1a604d..2454795cea8e535bcbbcf3785b08ced7e150d61f 100644
--- a/c/main
+++ b/c/main
@@ -289,6 +289,7 @@ static void open_configure_window(int at_x, int at_y)
         ((Gadget *)gadget)->hdr.flags |= (channel[i].category >= 0 ? 10 : 11) << Slider_BarColourShift;
         if (channel[i].fixed) ((Gadget *)gadget)->hdr.flags |= Gadget_Faded;
         error_trap(window_add_gadget(0, config_window_id, (Gadget *)gadget, NULL), 0);
+        error_trap(slider_set_bounds(7, config_window_id, 2+i*4, channel[i].mingain, channel[i].maxgain, channel[i].step), 0);
     }
 
     memcpy(gadget, gadget_template[3], gadget_template_size[3]);
diff --git a/c/sound b/c/sound
index 1168128a3834d9c703c3713a733b847675e8b661..d0d2c346382867807caf336412ea2ebeaad5f2b3 100644
--- a/c/sound
+++ b/c/sound
@@ -47,6 +47,15 @@ unsigned int nchannels;
 static int   menu_to_voice_map[16];
 static int   cmos_voice, cmos_volume;
 
+typedef struct
+{
+    unsigned short flags;
+    signed short category;
+    int mingain;
+    int maxgain;
+    int step;
+} mixer_features;
+
 /*---------------------------------------------------------------------------*
  * sound_read_channel_info                                                   *
  *                                                                           *
@@ -65,19 +74,49 @@ void sound_read_channel_info(void)
                      &block_size), 1);
     nchannels = -space_needed / block_size;
     if (nchannels > MAX_CHANNELS) nchannels = MAX_CHANNELS;
-    struct { unsigned short flags; signed short category; } info[nchannels];
+    char buffer[nchannels*block_size];
     error_trap(_swix(SoundCtrl_ExamineMixer, _INR(0,2)|_OUT(4),
                      0,
-                     info,
-                     sizeof info,
+                     buffer,
+                     sizeof buffer,
                      &nchannels), 1);
     for (int i = 0; i < nchannels; i++)
     {
-        channel[i].category = info[i].category;
+        mixer_features *info = (mixer_features *) (buffer+(block_size*i));
+        channel[i].category = info->category;
         channel[i].index = -1;
-        channel[i].muted_by_default = info[i].flags & 4;
-        channel[i].fixed = info[i].flags & 1;
-        channel[i].mono = info[i].flags & 2;
+        channel[i].muted_by_default = info->flags & 4;
+        channel[i].fixed = info->flags & 1;
+        channel[i].mono = info->flags & 2;
+        if (block_size >= 16)
+        {
+            channel[i].mingain = info->mingain;
+            channel[i].maxgain = info->maxgain;
+            channel[i].step = info->step;
+        }
+        else
+        {
+            /* Use old limits of +0/-34.5, step 24 */
+            channel[i].mingain = (int) (-34.5*16);
+            channel[i].maxgain = 0;
+            channel[i].step = 24;
+        }
+        if (channel[i].step <= 0)
+            channel[i].step = 1;
+        /* Limit minimum gain to arbitrarily chosen value of -40dB
+           This is to avoid too much of the bar being taken up by negative
+           values if the mixer is capable of high attenuation (e.g. OMAP3 can
+           go from -80 to +24, but the +ve range is the one we're interested in
+           since it's a quiet system overall) */
+        if (channel[i].mingain < -40*16)
+        {
+            /* Ensure new value is still a multiple of the step size */
+            int steps = (40*16+channel[i].step-1)/channel[i].step;
+            channel[i].mingain = -steps*channel[i].step;
+        }
+        /* Sanity check */
+        if (channel[i].mingain >= channel[i].maxgain)
+            channel[i].mingain = channel[i].maxgain-16;
     }
     while (nchannels > 0)
     {
diff --git a/h/sound b/h/sound
index 3f4620f702f92c8d0a5a55c0fadfad8ecd11b566..7d75350158a766f53e95d9073f78bbcf7895fe6a 100644
--- a/h/sound
+++ b/h/sound
@@ -38,6 +38,9 @@ extern struct channel
   bool fixed;
   bool mono;
   bool muted_by_default;
+  int mingain;
+  int maxgain;
+  int step;
 }
 channel[MAX_CHANNELS];