[PATCH] aoa: tas: add missing bass/treble controls
authorJohannes Berg <johannes@sipsolutions.net>
Mon, 10 Jul 2006 11:44:41 +0000 (04:44 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 10 Jul 2006 20:24:20 +0000 (13:24 -0700)
This patch adds the bass/treble controls to snd-aoa that snd-powermac always
had for tas3004 based machines.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h [new file with mode: 0644]
sound/aoa/codecs/snd-aoa-codec-tas.c

diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
new file mode 100644 (file)
index 0000000..69b6113
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * This file is only included exactly once!
+ *
+ * The tables here are derived from the tas3004 datasheet,
+ * modulo typo corrections and some smoothing...
+ */
+
+#define TAS3004_TREBLE_MIN     0
+#define TAS3004_TREBLE_MAX     72
+#define TAS3004_BASS_MIN       0
+#define TAS3004_BASS_MAX       72
+#define TAS3004_TREBLE_ZERO    36
+#define TAS3004_BASS_ZERO      36
+
+static u8 tas3004_treble_table[] = {
+       150, /* -18 dB */
+       149,
+       148,
+       147,
+       146,
+       145,
+       144,
+       143,
+       142,
+       141,
+       140,
+       139,
+       138,
+       137,
+       136,
+       135,
+       134,
+       133,
+       132,
+       131,
+       130,
+       129,
+       128,
+       127,
+       126,
+       125,
+       124,
+       123,
+       122,
+       121,
+       120,
+       119,
+       118,
+       117,
+       116,
+       115,
+       114, /* 0 dB */
+       113,
+       112,
+       111,
+       109,
+       108,
+       107,
+       105,
+       104,
+       103,
+       101,
+       99,
+       98,
+       96,
+       93,
+       91,
+       89,
+       86,
+       83,
+       81,
+       77,
+       74,
+       71,
+       67,
+       63,
+       59,
+       54,
+       49,
+       44,
+       38,
+       32,
+       26,
+       19,
+       10,
+       4,
+       2,
+       1, /* +18 dB */
+};
+
+static inline u8 tas3004_treble(int idx)
+{
+       return tas3004_treble_table[idx];
+}
+
+/* I only save the difference here to the treble table
+ * so that the binary is smaller...
+ * I have also ignored completely differences of
+ * +/- 1
+ */
+static s8 tas3004_bass_diff_to_treble[] = {
+       2, /* 7 dB, offset 50 */
+       2,
+       2,
+       2,
+       2,
+       1,
+       2,
+       2,
+       2,
+       3,
+       4,
+       4,
+       5,
+       6,
+       7,
+       8,
+       9,
+       10,
+       11,
+       14,
+       13,
+       8,
+       1, /* 18 dB */
+};
+
+static inline u8 tas3004_bass(int idx)
+{
+       u8 result = tas3004_treble_table[idx];
+
+       if (idx >= 50)
+               result += tas3004_bass_diff_to_treble[idx-50];
+       return result;
+}
index 009f57576f9c8081c4236310aa1cc3c140bc9540..16c0b6b0a80521eb90134bf50acfa46b842c9b0e 100644 (file)
@@ -72,6 +72,7 @@ MODULE_DESCRIPTION("tas codec driver for snd-aoa");
 
 #include "snd-aoa-codec-tas.h"
 #include "snd-aoa-codec-tas-gain-table.h"
+#include "snd-aoa-codec-tas-basstreble.h"
 #include "../aoa.h"
 #include "../soundbus/soundbus.h"
 
@@ -87,6 +88,7 @@ struct tas {
                                hw_enabled:1;
        u8                      cached_volume_l, cached_volume_r;
        u8                      mixer_l[3], mixer_r[3];
+       u8                      bass, treble;
        u8                      acr;
        int                     drc_range;
 };
@@ -128,6 +130,22 @@ static void tas3004_set_drc(struct tas *tas)
        tas_write_reg(tas, TAS_REG_DRC, 6, val);
 }
 
+static void tas_set_treble(struct tas *tas)
+{
+       u8 tmp;
+
+       tmp = tas3004_treble(tas->treble);
+       tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
+}
+
+static void tas_set_bass(struct tas *tas)
+{
+       u8 tmp;
+
+       tmp = tas3004_bass(tas->bass);
+       tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
+}
+
 static void tas_set_volume(struct tas *tas)
 {
        u8 block[6];
@@ -485,6 +503,89 @@ static struct snd_kcontrol_new capture_source_control = {
        .put = tas_snd_capture_source_put,
 };
 
+static int tas_snd_treble_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = TAS3004_TREBLE_MIN;
+       uinfo->value.integer.max = TAS3004_TREBLE_MAX;
+       return 0;
+}
+
+static int tas_snd_treble_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->treble;
+       return 0;
+}
+
+static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->treble == ucontrol->value.integer.value[0])
+               return 0;
+
+       tas->treble = ucontrol->value.integer.value[0];
+       if (tas->hw_enabled)
+               tas_set_treble(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new treble_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Treble",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_treble_info,
+       .get = tas_snd_treble_get,
+       .put = tas_snd_treble_put,
+};
+
+static int tas_snd_bass_info(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       uinfo->value.integer.min = TAS3004_BASS_MIN;
+       uinfo->value.integer.max = TAS3004_BASS_MAX;
+       return 0;
+}
+
+static int tas_snd_bass_get(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = tas->bass;
+       return 0;
+}
+
+static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+       if (tas->bass == ucontrol->value.integer.value[0])
+               return 0;
+
+       tas->bass = ucontrol->value.integer.value[0];
+       if (tas->hw_enabled)
+               tas_set_bass(tas);
+       return 1;
+}
+
+static struct snd_kcontrol_new bass_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Bass",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = tas_snd_bass_info,
+       .get = tas_snd_bass_get,
+       .put = tas_snd_bass_put,
+};
 
 static struct transfer_info tas_transfers[] = {
        {
@@ -541,9 +642,10 @@ static int tas_reset_init(struct tas *tas)
        tas3004_set_drc(tas);
 
        /* Set treble & bass to 0dB */
-       tmp = 114;
-       tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp);
-       tas_write_reg(tas, TAS_REG_BASS, 1, &tmp);
+       tas->treble = TAS3004_TREBLE_ZERO;
+       tas->bass = TAS3004_BASS_ZERO;
+       tas_set_treble(tas);
+       tas_set_bass(tas);
 
        tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
        if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
@@ -682,6 +784,14 @@ static int tas_init_codec(struct aoa_codec *codec)
        if (err)
                goto error;
 
+       err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas));
+       if (err)
+               goto error;
+
+       err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas));
+       if (err)
+               goto error;
+
        return 0;
  error:
        tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);