Index: uspace/drv/audio/sb16/mixer.c
===================================================================
--- uspace/drv/audio/sb16/mixer.c	(revision 365f25998562ba995ec439e31ec4b29f8b9798e8)
+++ uspace/drv/audio/sb16/mixer.c	(revision c799138bf81eb70094913af3d4fab04d7d8b72a2)
@@ -45,96 +45,69 @@
 } channel_t;
 
-typedef struct volume_item {
-	const char *description;
-	uint8_t channels;
-	const channel_t *channel_table;
-} volume_item_t;
-
 /* CT1335 channels */
 static const channel_t channels_table_ct1335[] = {
-	{ "Mono", 0x02, 1, 8, false }, /* Master, Mono, 3bit volume level */
-	{ "Mono", 0x06, 1, 8, false }, /* Midi, Mono, 3bit volume level */
-	{ "Mono", 0x08, 1, 8, false }, /* CD, Mono, 3bit volume level */
-	{ "Mono", 0x0a, 1, 4, false }, /* Voice, Mono, 2bit volume level */
+	{ "Master", 0x02, 1, 8, false }, /* Master, Mono, 3bit volume level */
+	{ "Midi", 0x06, 1, 8, false }, /* Midi, Mono, 3bit volume level */
+	{ "CD", 0x08, 1, 8, false }, /* CD, Mono, 3bit volume level */
+	{ "Voice", 0x0a, 1, 4, false }, /* Voice, Mono, 2bit volume level */
 };
 
 /* CT1345 channels */
 static const channel_t channels_table_ct1345[] = {
-	{ "Left", 0x22, 5, 8, true }, /* Master, Left, 3bit volume level */
-	{ "Right", 0x22, 1, 8, true }, /* Master, Right, 3bit volume level */
-	{ "Left", 0x26, 5, 8, true }, /* Midi, Left, 3bit volume level */
-	{ "Right", 0x26, 1, 8, true }, /* Midi, Right, 3bit volume level */
-	{ "Left", 0x28, 5, 8, true }, /* CD, Left, 3bit volume level */
-	{ "Right", 0x28, 1, 8, true }, /* CD, Right, 3bit volume level */
-	{ "Left", 0x2e, 5, 8, true }, /* Line, Left, 3bit volume level */
-	{ "Right", 0x2e, 1, 8, true }, /* Line, Right, 3bit volume level */
-	{ "Left", 0x04, 5, 8, true }, /* Voice, Left, 3bit volume level */
-	{ "Right", 0x04, 1, 8, true }, /* Voice, Right, 3bit volume level */
-	{ "Mono", 0x0a, 1, 4, false }, /* Mic, Mono, 2bit volume level */
+	{ "Master Left", 0x22, 5, 8, true }, /* Master, Left, 3bit volume level */
+	{ "Master Right", 0x22, 1, 8, true }, /* Master, Right, 3bit volume level */
+	{ "MIDI Left", 0x26, 5, 8, true }, /* Midi, Left, 3bit volume level */
+	{ "MIDI Right", 0x26, 1, 8, true }, /* Midi, Right, 3bit volume level */
+	{ "CD Left", 0x28, 5, 8, true }, /* CD, Left, 3bit volume level */
+	{ "CD Right", 0x28, 1, 8, true }, /* CD, Right, 3bit volume level */
+	{ "Line In Left", 0x2e, 5, 8, true }, /* Line, Left, 3bit volume level */
+	{ "Line In Right", 0x2e, 1, 8, true }, /* Line, Right, 3bit volume level */
+	{ "Voice Left", 0x04, 5, 8, true }, /* Voice, Left, 3bit volume level */
+	{ "Voice Right", 0x04, 1, 8, true }, /* Voice, Right, 3bit volume level */
+	{ "Mic", 0x0a, 1, 4, false }, /* Mic, Mono, 2bit volume level */
 };
 
 /* CT1745 channels */
 static const channel_t channels_table_ct1745[] = {
-	{ "Left", 0x30, 3, 32, false },  /* Master, Left, 5bit volume level */
-	{ "Right", 0x31, 3, 32, false }, /* Master, Right, 5bit volume level */
-	{ "Left", 0x32, 3, 32, false },  /* Voice, Left, 5bit volume level */
-	{ "Right", 0x33, 3, 32, false }, /* Voice, Right, 5bit volume level */
-	{ "Left", 0x34, 3, 32, false }, /* MIDI, Left, 5bit volume level */
-	{ "Right", 0x35, 3, 32, false }, /* MIDI, Right, 5bit volume level */
-	{ "Left", 0x36, 3, 32, false }, /* CD, Left, 5bit volume level */
-	{ "Right", 0x37, 3, 32, false }, /* CD, Right, 5bit volume level */
-	{ "Left", 0x38, 3, 32, false }, /* Line, Left, 5bit volume level */
-	{ "Right", 0x39, 3, 32, false }, /* Line, Right, 5bit volume level */
-	{ "Mono", 0x3a, 3, 32, false }, /* Mic, Mono, 5bit volume level */
-	{ "Mono", 0x3b, 6, 4, false }, /* PC speaker, Mono, 2bit level */
-	{ "Left", 0x3f, 6, 4, false }, /* Input Gain, Left, 2bit level */
-	{ "Right", 0x40, 6, 4, false }, /* Input Gain, Right, 2bit level */
-	{ "Left", 0x41, 6, 4, false }, /* Output Gain, Left, 2bit level */
-	{ "Right", 0x42, 6, 4, false }, /* Output Gain, Right, 2bit level */
-	{ "Left", 0x44, 4, 16, false }, /* Treble, Left, 4bit volume level */
-	{ "Right", 0x45, 4, 16, false }, /* Treble, Right, 4bit volume level */
-	{ "Left", 0x46, 4, 16, false }, /* Bass, Left, 4bit volume level */
-	{ "Right", 0x47, 4, 16, false }, /* Bass, Right, 4bit volume level */
-};
-
-static const volume_item_t volume_ct1335[] = {
-	{ "Master", 1, &channels_table_ct1335[0] },
-	{ "MIDI", 1, &channels_table_ct1335[1] },
-	{ "CD", 1, &channels_table_ct1335[2] },
-	{ "Voice", 1, &channels_table_ct1335[3] },
-};
-
-static const volume_item_t volume_ct1345[] = {
-	{ "Master", 2, &channels_table_ct1345[0] },
-	{ "Voice", 2, &channels_table_ct1345[8] },
-	{ "Mic", 1, &channels_table_ct1345[10] },
-	{ "MIDI", 2, &channels_table_ct1345[2] },
-	{ "CD", 2, &channels_table_ct1345[4] },
-	{ "Line", 2, &channels_table_ct1345[6] },
-};
-
-static const volume_item_t volume_ct1745[] = {
-	{ "Master", 2, &channels_table_ct1745[0] },
-	{ "Voice", 2, &channels_table_ct1745[2] },
-	{ "MIDI", 2, &channels_table_ct1745[4] },
-	{ "CD", 2, &channels_table_ct1745[6] },
-	{ "Line", 2, &channels_table_ct1745[8] },
-	{ "Mic", 1, &channels_table_ct1745[10] },
-	{ "PC Speaker", 1, &channels_table_ct1745[11] },
-	{ "Input Gain", 2, &channels_table_ct1745[12] },
-	{ "Output Gain", 2, &channels_table_ct1745[14] },
-	{ "Treble", 2, &channels_table_ct1745[16] },
-	{ "Bass", 2, &channels_table_ct1745[18] },
+	{ "Master Left", 0x30, 3, 32, false },  /* Master, Left, 5bit volume level */
+	{ "Master Right", 0x31, 3, 32, false }, /* Master, Right, 5bit volume level */
+	{ "Voice Left", 0x32, 3, 32, false },  /* Voice, Left, 5bit volume level */
+	{ "Voice Right", 0x33, 3, 32, false }, /* Voice, Right, 5bit volume level */
+	{ "MIDI Left", 0x34, 3, 32, false }, /* MIDI, Left, 5bit volume level */
+	{ "MIDI Right", 0x35, 3, 32, false }, /* MIDI, Right, 5bit volume level */
+	{ "CD Left", 0x36, 3, 32, false }, /* CD, Left, 5bit volume level */
+	{ "CD Right", 0x37, 3, 32, false }, /* CD, Right, 5bit volume level */
+	{ "Line In Left", 0x38, 3, 32, false }, /* Line, Left, 5bit volume level */
+	{ "Line In Right", 0x39, 3, 32, false }, /* Line, Right, 5bit volume level */
+	{ "Mic", 0x3a, 3, 32, false }, /* Mic, Mono, 5bit volume level */
+	{ "PC Speaker", 0x3b, 6, 4, false }, /* PC speaker, Mono, 2bit level */
+	{ "Input Gain Left", 0x3f, 6, 4, false }, /* Input Gain, Left, 2bit level */
+	{ "Input Gain Right", 0x40, 6, 4, false }, /* Input Gain, Right, 2bit level */
+	{ "Output Gain Left", 0x41, 6, 4, false }, /* Output Gain, Left, 2bit level */
+	{ "Output Gain Right", 0x42, 6, 4, false }, /* Output Gain, Right, 2bit level */
+	{ "Treble Left", 0x44, 4, 16, false }, /* Treble, Left, 4bit volume level */
+	{ "Treble Right", 0x45, 4, 16, false }, /* Treble, Right, 4bit volume level */
+	{ "Bass Left", 0x46, 4, 16, false }, /* Bass, Left, 4bit volume level */
+	{ "Bass Right", 0x47, 4, 16, false }, /* Bass, Right, 4bit volume level */
 };
 
 static const struct {
-	const volume_item_t *table;
+	const channel_t *table;
 	size_t count;
 } volume_table[] = {
 	[SB_MIXER_NONE] = { NULL, 0 },
 	[SB_MIXER_UNKNOWN] = { NULL, 0 },
-	[SB_MIXER_CT1335] = { volume_ct1335, ARRAY_SIZE(volume_ct1335) },
-	[SB_MIXER_CT1345] = { volume_ct1345, ARRAY_SIZE(volume_ct1345) },
-	[SB_MIXER_CT1745] = { volume_ct1745, ARRAY_SIZE(volume_ct1745) },
+	[SB_MIXER_CT1335] = {
+	    channels_table_ct1335,
+	    ARRAY_SIZE(channels_table_ct1335),
+	},
+	[SB_MIXER_CT1345] = {
+	    channels_table_ct1345,
+	    ARRAY_SIZE(channels_table_ct1345),
+	},
+	[SB_MIXER_CT1745] = {
+	    channels_table_ct1745,
+	    ARRAY_SIZE(channels_table_ct1745),
+	},
 };
 
@@ -177,85 +150,72 @@
 }
 
-int sb_mixer_get_control_item_info(const sb_mixer_t *mixer, unsigned index,
-    const char** name, unsigned *channels)
-{
-	assert(mixer);
-	if (index > volume_table[mixer->type].count)
+int sb_mixer_get_control_item_info(const sb_mixer_t *mixer, unsigned item,
+    const char** name, unsigned *levels)
+{
+	assert(mixer);
+	if (item > volume_table[mixer->type].count)
 		return ENOENT;
 
-	const volume_item_t *item = &volume_table[mixer->type].table[index];
+	const channel_t *ch = &volume_table[mixer->type].table[item];
 	if (name)
-		*name = item->description;
-	if (channels)
-		*channels = item->channels;
-	return EOK;
-}
-
-int sb_mixer_get_channel_info(const sb_mixer_t *mixer, unsigned index,
-    unsigned channel, const char **name, unsigned *levels)
-{
-	assert(mixer);
-	if (index > volume_table[mixer->type].count)
+		*name = ch->name;
+	if (levels)
+		*levels = ch->volume_levels;
+	return EOK;
+}
+
+/**
+ * Write new volume level from mixer registers.
+ * @param mixer SB Mixer to use.
+ * @param index Control item(channel) index.
+ * @param value New volume level.
+ * @return Error code.
+ */
+int sb_mixer_get_control_item_value(const sb_mixer_t *mixer, unsigned item,
+    unsigned *value)
+{
+	assert(mixer);
+	if (!value)
+		return EBADMEM;
+	if (item > volume_table[mixer->type].count)
 		return ENOENT;
 
-	const volume_item_t *item = &volume_table[mixer->type].table[index];
-	if (channel > item->channels)
+	const channel_t *chan = &volume_table[mixer->type].table[item];
+	pio_write_8(&mixer->regs->mixer_address, chan->address);
+	*value = (pio_read_8(&mixer->regs->mixer_data) >> chan->shift)
+	    & (chan->volume_levels - 1);
+	return EOK;
+}
+
+/**
+ * Write new volume level to mixer registers.
+ * @param mixer SB Mixer to use.
+ * @param index Control item(channel) index.
+ * @param value New volume level.
+ * @return Error code.
+ */
+int sb_mixer_set_control_item_value(const sb_mixer_t *mixer, unsigned item,
+    unsigned value)
+{
+	assert(mixer);
+	if (item > volume_table[mixer->type].count)
 		return ENOENT;
 
-	const channel_t *chan = &item->channel_table[channel];
-	if (name)
-		*name = chan->name;
-	if (levels)
-		*levels = chan->volume_levels;
-	return EOK;
-}
-
-int sb_mixer_set_volume_level(const sb_mixer_t *mixer,
-    unsigned index, unsigned channel, unsigned level)
-{
-	if (mixer->type == SB_MIXER_UNKNOWN || mixer->type == SB_MIXER_NONE)
-		return ENOTSUP;
-	if (index >= volume_table[mixer->type].count)
-		return ENOENT;
-	if (channel >= volume_table[mixer->type].table[index].channels)
-		return ENOENT;
-
-	const channel_t *chan =
-	    &volume_table[mixer->type].table[index].channel_table[channel];
-
-	if (level >= chan->volume_levels)
-		level = chan->volume_levels - 1;
+	const channel_t *chan = &volume_table[mixer->type].table[item];
+	if (value >= chan->volume_levels)
+		value = chan->volume_levels - 1;
 
 	pio_write_8(&mixer->regs->mixer_address, chan->address);
 
-	uint8_t value = 0;
+	uint8_t regv = 0;
 	if (chan->preserve_bits) {
-		value = pio_read_8(&mixer->regs->mixer_data);
-		value &= ~(uint8_t)((chan->volume_levels - 1) << chan->shift);
+		regv = pio_read_8(&mixer->regs->mixer_data);
+		regv &= ~(uint8_t)((chan->volume_levels - 1) << chan->shift);
 	}
 
-	value |= level << chan->shift;
-	pio_write_8(&mixer->regs->mixer_data, value);
-	ddf_log_note("Channel %s %s volume set to: %u.",
-	    volume_table[mixer->type].table[index].description,
-	    chan->name, level);
-	return EOK;
-}
-
-unsigned sb_mixer_get_volume_level(const sb_mixer_t *mixer, unsigned index,
-    unsigned channel)
-{
-	assert(mixer);
-	if (mixer->type == SB_MIXER_UNKNOWN
-	    || mixer->type == SB_MIXER_NONE
-	    || (index >= volume_table[mixer->type].count)
-	    || (channel >= volume_table[mixer->type].table[index].channels))
-		return 0;
-
-	const channel_t *chan =
-	    &volume_table[mixer->type].table[index].channel_table[channel];
-
-	pio_write_8(&mixer->regs->mixer_address, chan->address);
-	return (pio_read_8(&mixer->regs->mixer_data) >> chan->shift)
-	    & (chan->volume_levels - 1);
-}
+	regv |= value << chan->shift;
+	pio_write_8(&mixer->regs->mixer_data, regv);
+	ddf_log_note("Item %s new value is: %u.",
+	    volume_table[mixer->type].table[item].name, value);
+	return EOK;
+}
