Fixed ioctl code and added coeff setting example code
[aic34-eq] / kernel-2.6.28 / sound / soc / codecs / tlv320aic3x.c
index 20747a6..ec84be5 100644 (file)
 static int hp_dac_lim = 9;
 module_param(hp_dac_lim, int, 0);
 
 static int hp_dac_lim = 9;
 module_param(hp_dac_lim, int, 0);
 
-/* Data for reading/writing to the IIR Filter hwdep */
-struct aic3x_iir_coeffs {
-       short N0, N1, N2, D1, D2;
-       short N3, N4, N5, D4, D5;
-};
-
 struct aic3x_dacfilter_t {
        struct aic3x_iir_coeffs coeffs;
        int state;
 struct aic3x_dacfilter_t {
        struct aic3x_iir_coeffs coeffs;
        int state;
@@ -184,14 +178,15 @@ static int aic3x_write(struct snd_soc_codec *codec,
 {
        static char curpage = -1;
        u8 data[2], page = 0;
 {
        static char curpage = -1;
        u8 data[2], page = 0;
-    printk("MNZ: aic3x_write(reg = %i, val = %x), curpage = %i\n",
-    reg, value, curpage);
+
        /*mutex_lock(&codec->mutex);*/
        
        if (reg > 127){
                reg -= 128;
                page = 1;
        }
        /*mutex_lock(&codec->mutex);*/
        
        if (reg > 127){
                reg -= 128;
                page = 1;
        }
+    //printk("MNZ: aic3x_write(reg = %i, val = 0x%x, page = %i)\n",
+    //reg, value, page);
        if(reg && curpage != page){
                data[0] = 0;
                data[1] = page;
        if(reg && curpage != page){
                data[0] = 0;
                data[1] = page;
@@ -201,7 +196,6 @@ static int aic3x_write(struct snd_soc_codec *codec,
                } else {
                        curpage = page;
                }
                } else {
                        curpage = page;
                }
-        printk("MNZ: aic3x_write(), switched to page%i\n", curpage);
        }
 
 
        }
 
 
@@ -375,7 +369,7 @@ static const char *aic3x_linein_mode_mux[] = { "single-ended", "differential" };
 static const char *aic3x_adc_hpf[] =
     { "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" };
 static const char *aic3x_dac_filt[] =
 static const char *aic3x_adc_hpf[] =
     { "Disabled", "0.0045xFs", "0.0125xFs", "0.025xFs" };
 static const char *aic3x_dac_filt[] =
-       { "Off", "On", "Custom" };
+       { "Off", "Bass/Treble", "Custom" };
 
 #define LDAC_ENUM      0
 #define RDAC_ENUM      1
 
 #define LDAC_ENUM      0
 #define RDAC_ENUM      1
@@ -454,14 +448,36 @@ static int tlv320alc3x_info_volsw(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
        return 0;
 }
 
-/* DAC Filter Functions */
+/* DAC and De-emphasis Filter Functions */
+int aic3x_deemph_set_coeffs(struct snd_soc_codec *codec,
+               int N0, int N1, int D1){
+    printk("MNZ: setting deemph coeffs\n");
+       snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL, DEEMPH_ON, 0);
+
+       aic3x_write_coeff(codec, DEEMPH_LEFT_N0, N0);
+       aic3x_write_coeff(codec, DEEMPH_LEFT_N1, N1);
+       aic3x_write_coeff(codec, DEEMPH_LEFT_D1, D1);
+       aic3x_write_coeff(codec, DEEMPH_RIGHT_N0, N0);
+       aic3x_write_coeff(codec, DEEMPH_RIGHT_N1, N1);
+       aic3x_write_coeff(codec, DEEMPH_RIGHT_D1, D1);
+       
+       return 0;
+}
+EXPORT_SYMBOL_GPL(aic3x_deemph_set_coeffs);
+
+int aic3x_deemph_set_state(struct snd_soc_codec *codec, int state){
+       printk("MNZ: Setting De-Emph filter: %i\n", state);
+       if(state) state = DEEMPH_ON;
+       else state = 0;
+       return snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL,
+               DEEMPH_ON, state);
+}
+EXPORT_SYMBOL_GPL(aic3x_deemph_set_state);
 
 static int aic3x_dacfilter_write_coeffs
     (struct snd_soc_codec *codec, struct aic3x_iir_coeffs *coeffs)
 {
 
 static int aic3x_dacfilter_write_coeffs
     (struct snd_soc_codec *codec, struct aic3x_iir_coeffs *coeffs)
 {
-       struct aic3x_priv *aic3x = codec->private_data;
        printk("MNZ: dacfilter_write_coeffs\n");
        printk("MNZ: dacfilter_write_coeffs\n");
-       snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL, EFFECTS_ON, 0);
        aic3x_write_coeff(codec, EFFECTS_LEFT_N0, coeffs->N0);
        aic3x_write_coeff(codec, EFFECTS_LEFT_N1, coeffs->N1);
        aic3x_write_coeff(codec, EFFECTS_LEFT_N2, coeffs->N2);
        aic3x_write_coeff(codec, EFFECTS_LEFT_N0, coeffs->N0);
        aic3x_write_coeff(codec, EFFECTS_LEFT_N1, coeffs->N1);
        aic3x_write_coeff(codec, EFFECTS_LEFT_N2, coeffs->N2);
@@ -484,36 +500,58 @@ static int aic3x_dacfilter_write_coeffs
        aic3x_write_coeff(codec, EFFECTS_RIGHT_D4, coeffs->D4);
        aic3x_write_coeff(codec, EFFECTS_RIGHT_D5, coeffs->D5);
        
        aic3x_write_coeff(codec, EFFECTS_RIGHT_D4, coeffs->D4);
        aic3x_write_coeff(codec, EFFECTS_RIGHT_D5, coeffs->D5);
        
-       snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL, EFFECTS_ON, EFFECTS_ON);
+       return 1;
+}
 
 
+int aic3x_dacfilter_set_coeffs
+    (struct snd_soc_codec *codec, struct aic3x_iir_coeffs *coeffs)
+{
+       struct aic3x_priv *aic3x = codec->private_data;
        memcpy((void*)&aic3x->dacfilter.coeffs, (void*)coeffs,
        memcpy((void*)&aic3x->dacfilter.coeffs, (void*)coeffs,
-                       sizeof(struct aic3x_iir_coeffs));       
+                       sizeof(struct aic3x_iir_coeffs));
+       if(aic3x->dacfilter.state == 2)
+               aic3x_dacfilter_set_state(codec, 0);
        return 0;
 }
        return 0;
 }
+EXPORT_SYMBOL_GPL(aic3x_dacfilter_set_coeffs);
 
 
-static int aic3x_dacfilter_set_state(struct snd_soc_codec *codec,
-               int state)
+int aic3x_dacfilter_set_state(struct snd_soc_codec *codec, int state)
 {
 {
+       printk("MNZ: dacfilter_set_state to %i\n", state);
        struct aic3x_priv *aic3x = codec->private_data;
        struct aic3x_priv *aic3x = codec->private_data;
-       printk("MNZ: dacfilter_set_state(state = %i)\n", state);
-
+       int ret = 0;
        if(aic3x->dacfilter.state == state) return 0;
        if(aic3x->dacfilter.state == state) return 0;
-       
-       aic3x->dacfilter.state = state;
 
 
-       if(state == 0)
-               snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL,
+       snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL,
                        EFFECTS_ON, 0);
                        EFFECTS_ON, 0);
-       else if(state == 1) {}
+
+       if(state == 0)
+               ret = 1;
+       else if(state == 1)
+               ret = 1;
                /* FIXME MNZ. Set preset from current chosen preset */
                /* FIXME MNZ. Set preset from current chosen preset */
-       else if (state == 2)
-               return aic3x_dacfilter_write_coeffs(codec,
-                                       &aic3x->dacfilter.coeffs);      
-       return 0;
+       else if (state == 2){
+               ret = aic3x_dacfilter_write_coeffs(codec,
+                                       &aic3x->dacfilter.coeffs);
+               if(ret) snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL,
+                       EFFECTS_ON, EFFECTS_ON);
+       }
+       else ret = 0;
+
+       if(ret) aic3x->dacfilter.state = state;
+       return ret;
 }
 
 }
 
+EXPORT_SYMBOL_GPL(aic3x_dacfilter_set_state);
+
 /* DAC Filter hwdep device callbacks */
 
 /* DAC Filter hwdep device callbacks */
 
+static int snd_hwdep_dacfilter_open_aic3x(struct snd_hwdep *hw,
+       struct file *file)
+{
+       return 0;
+}
+
 static int snd_hwdep_dacfilter_ioctl_aic3x(struct snd_hwdep *hw,
        struct file *file, unsigned int cmd, unsigned long arg)
 {
 static int snd_hwdep_dacfilter_ioctl_aic3x(struct snd_hwdep *hw,
        struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -523,8 +561,8 @@ static int snd_hwdep_dacfilter_ioctl_aic3x(struct snd_hwdep *hw,
         */
        struct snd_soc_codec *codec = hw->private_data;
        if (cmd != 1) return -EINVAL;
         */
        struct snd_soc_codec *codec = hw->private_data;
        if (cmd != 1) return -EINVAL;
+       printk("MNZ: IOCTL: cmd = %i, arg = %i\n", cmd, *((int*)arg));
        return aic3x_dacfilter_set_state(codec, *((int*)arg));
        return aic3x_dacfilter_set_state(codec, *((int*)arg));
-       return 0;
 }
 
 static long snd_hwdep_dacfilter_read_aic3x(struct snd_hwdep *hw,
 }
 
 static long snd_hwdep_dacfilter_read_aic3x(struct snd_hwdep *hw,
@@ -545,17 +583,16 @@ static long snd_hwdep_dacfilter_write_aic3x(struct snd_hwdep *hw,
 
        ((struct aic3x_priv*)codec->private_data)->dacfilter.state = 2;
        
 
        ((struct aic3x_priv*)codec->private_data)->dacfilter.state = 2;
        
-       return aic3x_dacfilter_write_coeffs(codec, 
+       return aic3x_dacfilter_set_coeffs(codec, 
                                                (struct aic3x_iir_coeffs*)buf);
 }
 
                                                (struct aic3x_iir_coeffs*)buf);
 }
 
-/* DAC filter and 3D depth alsa controls callbacks */
+/* DAC filter and 3D depth ALSA controls callbacks */
 
 static int snd_soc_get_dacfilter_aic3x(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 
 static int snd_soc_get_dacfilter_aic3x(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-printk("MNZ: get_dacfilter getting state: %i\n",((struct aic3x_priv*)codec->private_data)->dacfilter.state );  
        ucontrol->value.enumerated.item[0] = 
                ((struct aic3x_priv*)codec->private_data)->dacfilter.state;
        return 0;
        ucontrol->value.enumerated.item[0] = 
                ((struct aic3x_priv*)codec->private_data)->dacfilter.state;
        return 0;
@@ -565,7 +602,6 @@ static int snd_soc_put_dacfilter_aic3x(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       printk("MNZ: put_dacfilter setting to %i\n", ucontrol->value.enumerated.item[0]);
        if (ucontrol->value.enumerated.item[0] > 2)
                return -EINVAL;
        aic3x_dacfilter_set_state(codec, ucontrol->value.enumerated.item[0]);
        if (ucontrol->value.enumerated.item[0] > 2)
                return -EINVAL;
        aic3x_dacfilter_set_state(codec, ucontrol->value.enumerated.item[0]);
@@ -1506,8 +1542,11 @@ static int aic3x_init(struct snd_soc_device *socdev)
 {
        struct snd_soc_codec *codec = socdev->codec;
        struct aic3x_setup_data *setup = socdev->codec_data;
 {
        struct snd_soc_codec *codec = socdev->codec;
        struct aic3x_setup_data *setup = socdev->codec_data;
+       struct snd_hwdep *hwdep;
+    char hwdepid[] = "IIR Filter";
        int reg, ret = 0;
 
        int reg, ret = 0;
 
+       printk("MNZ: BEGIN aic3x_init\n");
        codec->name = "tlv320aic3x";
        codec->owner = THIS_MODULE;
        codec->read = aic3x_read_reg_cache;
        codec->name = "tlv320aic3x";
        codec->owner = THIS_MODULE;
        codec->read = aic3x_read_reg_cache;
@@ -1602,7 +1641,19 @@ static int aic3x_init(struct snd_soc_device *socdev)
 
        aic3x_add_controls(codec);
        aic3x_add_widgets(codec);
 
        aic3x_add_controls(codec);
        aic3x_add_widgets(codec);
+
+       if(snd_hwdep_new(codec->card, hwdepid, 0, &hwdep) == 0){
+               hwdep->private_data = codec;
+               sprintf(hwdep->name, hwdepid);
+               hwdep->ops.open = snd_hwdep_dacfilter_open_aic3x;
+               hwdep->ops.ioctl = snd_hwdep_dacfilter_ioctl_aic3x;
+               hwdep->ops.read = snd_hwdep_dacfilter_read_aic3x;
+               hwdep->ops.write = snd_hwdep_dacfilter_write_aic3x;
+               ((struct aic3x_priv*)codec->private_data)->hwdep = hwdep;
+       }
+
        ret = snd_soc_register_card(socdev);
        ret = snd_soc_register_card(socdev);
+
        if (ret < 0) {
                printk(KERN_ERR "aic3x: failed to register card\n");
                goto card_err;
        if (ret < 0) {
                printk(KERN_ERR "aic3x: failed to register card\n");
                goto card_err;
@@ -1610,6 +1661,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
 
        /* Set some defaults for coefficients */
        aic3x_write_coeff(codec, EFFECTS_3DATTEN, -32768);
 
        /* Set some defaults for coefficients */
        aic3x_write_coeff(codec, EFFECTS_3DATTEN, -32768);
+       printk("MNZ: END aic3x_init\n");
 
        return ret;
 
 
        return ret;
 
@@ -1726,7 +1778,6 @@ static int aic3x_probe(struct platform_device *pdev)
        struct aic3x_setup_data *setup;
        struct snd_soc_codec *codec;
        struct aic3x_priv *aic3x;
        struct aic3x_setup_data *setup;
        struct snd_soc_codec *codec;
        struct aic3x_priv *aic3x;
-       struct snd_hwdep *hwdep;
        int ret = 0;
 
        printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION);
        int ret = 0;
 
        printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION);
@@ -1761,15 +1812,6 @@ static int aic3x_probe(struct platform_device *pdev)
        /* Add other interfaces here */
 #endif
 
        /* Add other interfaces here */
 #endif
 
-       if(snd_hwdep_new(codec->card, "IIR Filter", 0, &hwdep) == 0){
-               printk("MNZ: hwdep initialized\n");
-        hwdep->private_data = codec;
-               hwdep->ops.ioctl = snd_hwdep_dacfilter_ioctl_aic3x;
-               hwdep->ops.read = snd_hwdep_dacfilter_read_aic3x;
-               hwdep->ops.write = snd_hwdep_dacfilter_write_aic3x;
-               aic3x->hwdep = hwdep;
-       }
-       
        if (ret != 0) {
                kfree(codec->private_data);
                kfree(codec);
        if (ret != 0) {
                kfree(codec->private_data);
                kfree(codec);