]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - sound/pci/ice1712/phase.c
[ALSA] switching rate in STAC9460 codec of Prodigy192
[linux-2.6-omap-h63xx.git] / sound / pci / ice1712 / phase.c
index 502da1c8b5f71946d070171f922b10ec46a66df0..c81efc2f8c95ec39231e9aa0bebcbea230cb7dde 100644 (file)
@@ -46,6 +46,7 @@
 #include "ice1712.h"
 #include "envy24ht.h"
 #include "phase.h"
+#include <sound/tlv.h>
 
 /* WM8770 registers */
 #define WM_DAC_ATTEN           0x00    /* DAC1-8 analog attenuation */
@@ -70,7 +71,7 @@
  * Logarithmic volume values for WM8770
  * Computed as 20 * Log10(255 / x)
  */
-static unsigned char wm_vol[256] = {
+static const unsigned char wm_vol[256] = {
        127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
        23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
        17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
@@ -152,35 +153,35 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
 }
 
 static unsigned char phase22_eeprom[] __devinitdata = {
-       0x00,   /* SYSCONF: 1xADC, 1xDACs */
-       0x80,   /* ACLINK: I2S */
-       0xf8,   /* I2S: vol, 96k, 24bit*/
-       0xc3,   /* SPDIF: out-en, out-int, spdif-in */
-       0xFF,   /* GPIO_DIR */
-       0xFF,   /* GPIO_DIR1 */
-       0xFF,   /* GPIO_DIR2 */
-       0x00,   /* GPIO_MASK */
-       0x00,   /* GPIO_MASK1 */
-       0x00,   /* GPIO_MASK2 */
-       0x00,   /* GPIO_STATE: */
-       0x00,   /* GPIO_STATE1: */
-       0x00,   /* GPIO_STATE2 */
+       [ICE_EEP2_SYSCONF]     = 0x00,  /* 1xADC, 1xDACs */
+       [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
+       [ICE_EEP2_I2S]         = 0xf8,  /* vol, 96k, 24bit */
+       [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
+       [ICE_EEP2_GPIO_DIR]    = 0xff,
+       [ICE_EEP2_GPIO_DIR1]   = 0xff,
+       [ICE_EEP2_GPIO_DIR2]   = 0xff,
+       [ICE_EEP2_GPIO_MASK]   = 0x00,
+       [ICE_EEP2_GPIO_MASK1]  = 0x00,
+       [ICE_EEP2_GPIO_MASK2]  = 0x00,
+       [ICE_EEP2_GPIO_STATE]  = 0x00,
+       [ICE_EEP2_GPIO_STATE1] = 0x00,
+       [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
 static unsigned char phase28_eeprom[] __devinitdata = {
-       0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
-       0x80,   /* ACLINK: I2S */
-       0xfc,   /* I2S: vol, 96k, 24bit, 192k */
-       0xc3,   /* SPDIF: out-en, out-int, spdif-in */
-       0xff,   /* GPIO_DIR */
-       0xff,   /* GPIO_DIR1 */
-       0x5f,   /* GPIO_DIR2 */
-       0x00,   /* GPIO_MASK */
-       0x00,   /* GPIO_MASK1 */
-       0x00,   /* GPIO_MASK2 */
-       0x00,   /* GPIO_STATE */
-       0x00,   /* GPIO_STATE1 */
-       0x00,   /* GPIO_STATE2 */
+       [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
+       [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
+       [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
+       [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
+       [ICE_EEP2_GPIO_DIR]    = 0xff,
+       [ICE_EEP2_GPIO_DIR1]   = 0xff,
+       [ICE_EEP2_GPIO_DIR2]   = 0x5f,
+       [ICE_EEP2_GPIO_MASK]   = 0x00,
+       [ICE_EEP2_GPIO_MASK1]  = 0x00,
+       [ICE_EEP2_GPIO_MASK2]  = 0x00,
+       [ICE_EEP2_GPIO_STATE]  = 0x00,
+       [ICE_EEP2_GPIO_STATE1] = 0x00,
+       [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
 /*
@@ -269,7 +270,7 @@ static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned sho
 /*
  * DAC mute control
  */
-#define wm_pcm_mute_info       phase28_mono_bool_info
+#define wm_pcm_mute_info       snd_ctl_boolean_mono_info
 
 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -325,10 +326,13 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
 
        snd_ice1712_save_gpio_status(ice);
        for (ch = 0; ch < 2; ch++) {
-               if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) {
+               unsigned int vol = ucontrol->value.integer.value[ch];
+               if (vol > WM_VOL_MAX)
+                       continue;
+               vol |= ice->spec.phase28.master[ch] & WM_VOL_MUTE;
+               if (vol != ice->spec.phase28.master[ch]) {
                        int dac;
-                       ice->spec.phase28.master[ch] &= WM_VOL_MUTE;
-                       ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch];
+                       ice->spec.phase28.master[ch] = vol;
                        for (dac = 0; dac < ice->num_total_dacs; dac += 2)
                                wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
                                           ice->spec.phase28.vol[dac + ch],
@@ -342,7 +346,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
 
 static int __devinit phase28_init(struct snd_ice1712 *ice)
 {
-       static unsigned short wm_inits_phase28[] = {
+       static const unsigned short wm_inits_phase28[] = {
                /* These come first to reduce init pop noise */
                0x1b, 0x044,            /* ADC Mux (AC'97 source) */
                0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
@@ -381,7 +385,7 @@ static int __devinit phase28_init(struct snd_ice1712 *ice)
 
        unsigned int tmp;
        struct snd_akm4xxx *ak;
-       unsigned short *p;
+       const unsigned short *p;
        int i;
 
        ice->num_total_dacs = 8;
@@ -461,10 +465,14 @@ static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *
        ofs = kcontrol->private_value & 0xff;
        snd_ice1712_save_gpio_status(ice);
        for (i = 0; i < voices; i++) {
-               idx  = WM_DAC_ATTEN + ofs + i;
-               if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) {
-                       ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE;
-                       ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i];
+               unsigned int vol;
+               vol = ucontrol->value.integer.value[i];
+               if (vol > 0x7f)
+                       continue;
+               vol |= ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE;
+               if (vol != ice->spec.phase28.vol[ofs+i]) {
+                       ice->spec.phase28.vol[ofs+i] = vol;
+                       idx  = WM_DAC_ATTEN + ofs + i;
                        wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i],
                                   ice->spec.phase28.master[i]);
                        change = 1;
@@ -526,13 +534,7 @@ static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
 /*
  * WM8770 master mute control
  */
-static int wm_master_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 2;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
+#define wm_master_mute_info            snd_ctl_boolean_stereo_info
 
 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -600,8 +602,10 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
        unsigned short ovol, nvol;
        int change = 0;
 
-       snd_ice1712_save_gpio_status(ice);
        nvol = ucontrol->value.integer.value[0];
+       if (nvol > PCM_RES)
+               return -EINVAL;
+       snd_ice1712_save_gpio_status(ice);
        nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
        ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
        if (ovol != nvol) {
@@ -613,21 +617,10 @@ static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
        return change;
 }
 
-/*
- */
-static int phase28_mono_bool_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
-{
-       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-       uinfo->count = 1;
-       uinfo->value.integer.min = 0;
-       uinfo->value.integer.max = 1;
-       return 0;
-}
-
 /*
  * Deemphasis
  */
-#define phase28_deemp_info     phase28_mono_bool_info
+#define phase28_deemp_info     snd_ctl_boolean_mono_info
 
 static int phase28_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
@@ -696,6 +689,9 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ct
        return 0;
 }
 
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
+
 static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -706,10 +702,13 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "Master Playback Volume",
                .info = wm_master_vol_info,
                .get = wm_master_vol_get,
-               .put = wm_master_vol_put
+               .put = wm_master_vol_put,
+               .tlv = { .p = db_scale_wm_dac }
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -721,11 +720,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "Front Playback Volume",
                .info = wm_vol_info,
                .get = wm_vol_get,
                .put = wm_vol_put,
-               .private_value = (2 << 8) | 0
+               .private_value = (2 << 8) | 0,
+               .tlv = { .p = db_scale_wm_dac }
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -737,11 +739,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "Rear Playback Volume",
                .info = wm_vol_info,
                .get = wm_vol_get,
                .put = wm_vol_put,
-               .private_value = (2 << 8) | 2
+               .private_value = (2 << 8) | 2,
+               .tlv = { .p = db_scale_wm_dac }
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -753,11 +758,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "Center Playback Volume",
                .info = wm_vol_info,
                .get = wm_vol_get,
                .put = wm_vol_put,
-               .private_value = (1 << 8) | 4
+               .private_value = (1 << 8) | 4,
+               .tlv = { .p = db_scale_wm_dac }
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -769,11 +777,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "LFE Playback Volume",
                .info = wm_vol_info,
                .get = wm_vol_get,
                .put = wm_vol_put,
-               .private_value = (1 << 8) | 5
+               .private_value = (1 << 8) | 5,
+               .tlv = { .p = db_scale_wm_dac }
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -785,11 +796,14 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "Side Playback Volume",
                .info = wm_vol_info,
                .get = wm_vol_get,
                .put = wm_vol_put,
-               .private_value = (2 << 8) | 6
+               .private_value = (2 << 8) | 6,
+               .tlv = { .p = db_scale_wm_dac }
        }
 };
 
@@ -803,10 +817,13 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                          SNDRV_CTL_ELEM_ACCESS_TLV_READ),
                .name = "PCM Playback Volume",
                .info = wm_pcm_vol_info,
                .get = wm_pcm_vol_get,
-               .put = wm_pcm_vol_put
+               .put = wm_pcm_vol_put,
+               .tlv = { .p = db_scale_wm_pcm }
        },
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,