X-Git-Url: http://git.maemo.org/git/?p=aic34-eq;a=blobdiff_plain;f=kernel-2.6.28%2Fsound%2Fsoc%2Fcodecs%2Ftlv320aic3x.c;h=ec84be56de3bf15560da8d28483c201f4d073c33;hp=b39b3ae2f48e27f1ffb4be83aa2db06f75c987eb;hb=HEAD;hpb=93fcb39776ddebc0cae03b14252925ea0d084d0d;ds=sidebyside diff --git a/kernel-2.6.28/sound/soc/codecs/tlv320aic3x.c b/kernel-2.6.28/sound/soc/codecs/tlv320aic3x.c index b39b3ae..ec84be5 100644 --- a/kernel-2.6.28/sound/soc/codecs/tlv320aic3x.c +++ b/kernel-2.6.28/sound/soc/codecs/tlv320aic3x.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "tlv320aic3x.h" @@ -54,12 +55,24 @@ static int hp_dac_lim = 9; module_param(hp_dac_lim, int, 0); +struct aic3x_dacfilter_t { + struct aic3x_iir_coeffs coeffs; + int state; +} aic3x_dacfilter = { + .coeffs = { + .N0 = 27619, .N1 = -27034, .N2 = 26461, .D1 = 32131, .D2 = -31506, + .N3 = 27619, .N4 = -27034, .N5 = 26461, .D4 = 32131, .D5 = -31506, + }, + .state = 0, +}; + /* codec private data */ struct aic3x_priv { unsigned int sysclk; int master; int prepare_reset; - u16 coeff_cache[AIC3X_COEFF_CACHE_SIZE]; + struct snd_hwdep *hwdep; + struct aic3x_dacfilter_t dacfilter; }; /* @@ -94,29 +107,33 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { 0x00, 0x00, 0x00, 0x00, /* 88 */ 0x00, 0x00, 0x00, 0x00, /* 92 */ 0x00, 0x00, 0x00, 0x00, /* 96 */ - 0x00, 0x00, 0x02, /* 100 */ -}; - -/* Page 1 registers store 2s compliment 16-bit numbers used for - * coefficients for effects. Each number is in 2 register, MSB followed - * by LSB. Therefore this array contains AIC3X_CACHEREGNUM/2 + 1 items. - */ -static const u16 aic3x_coeff[AIC3X_COEFF_CACHE_SIZE] = -{ - 0x00, /* Reg 0 */ - 0x6be3, 0x9666, 0x675d, 0x6be3, /* Reg 1 - 8 */ - 0x9666, 0x675d, 0x7d83, 0x84ee, /* 9 - 16 */ - 0x7d83, 0x84ee, 0x3955, 0xf32d, /* 17 - 24 */ - 0x537e, 0x6be3, 0x9666, 0x675d, /* 25 - 32 */ - 0x6be3, 0x9666, 0x675d, 0x7d83, /* 33 - 40 */ - 0x84ee, 0x7d83, 0x84ee, 0x3955, /* 41 - 48 */ - 0xf32d, 0x537e, 0x7fff, 0x0000, /* 49 - 56 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 57 - 64 */ - 0x3955, 0xf32d, 0x537e, 0x3955, /* 65 - 72 */ - 0xf32d, 0x537e, 0x0000, 0x0000, /* 73 - 80 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 81 - 88 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 89 - 96 */ - 0x0000, 0x0000, 0x0000, /* 97 - 102 */ + 0x00, 0x00, 0x02, 0x00, /* 100 */ + 0x00, 0x00, 0x00, 0x00, /* 104 */ + 0x00, 0x00, 0x00, 0x00, /* 108 */ + 0x00, 0x00, 0x00, 0x00, /* 112 */ + 0x00, 0x00, 0x00, 0x00, /* 116 */ + 0x00, 0x00, 0x00, 0x00, /* 120 */ + 0x00, 0x00, 0x00, 0x00, /* 124 */ + 0x01, 0x6b, 0xe3, 0x96, /* 128 */ + 0x66, 0x67, 0x5d, 0x6b, /* 132 */ + 0xe3, 0x96, 0x66, 0x67, /* 136 */ + 0x5d, 0x7d, 0x83, 0x84, /* 140 */ + 0xee, 0x7d, 0x83, 0x84, /* 144 */ + 0xee, 0x39, 0x55, 0xf3, /* 148 */ + 0x2d, 0x53, 0x7e, 0x6b, /* 152 */ + 0xe3, 0x96, 0x66, 0x67, /* 156 */ + 0x5d, 0x6b, 0xe3, 0x96, /* 160 */ + 0x66, 0x67, 0x5d, 0x7d, /* 164 */ + 0x83, 0x84, 0xee, 0x7d, /* 168 */ + 0x83, 0x84, 0xee, 0x39, /* 172 */ + 0x55, 0xf3, 0x2d, 0x53, /* 176 */ + 0x7e, 0x7f, 0xff, 0x00, /* 180 */ + 0x00, 0x00, 0x00, 0x00, /* 184 */ + 0x00, 0x00, 0x00, 0x00, /* 188 */ + 0x00, 0x39, 0x55, 0xf3, /* 192 */ + 0x2d, 0x53, 0x7e, 0x39, /* 196 */ + 0x55, 0xf3, 0x2d, 0x53, /* 200 */ + 0x7e, /* 204 */ }; /* @@ -131,10 +148,14 @@ static inline unsigned int aic3x_read_reg_cache(struct snd_soc_codec *codec, return cache[reg]; } -static inline unsigned int aic3x_read_coeff_cache(struct snd_soc_codec *codec, - unsigned int reg) { - u16 *cache = ((struct aic3x_priv*)codec->private_data)->coeff_cache; - return cache[COEFF_OFFSET(reg)]; +static inline int aic3x_read_coeff_reg_cache + (struct snd_soc_codec *codec, unsigned int msbreg) +{ + int val; + val = aic3x_read_reg_cache(codec, msbreg) << 8; + val |= aic3x_read_reg_cache(codec, msbreg+1); + if(val > 32767) val -= 65536; + return val; } /* @@ -152,59 +173,70 @@ static inline void aic3x_write_reg_cache(struct snd_soc_codec *codec, /* * write to the aic3x register space */ -static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) +static int aic3x_write(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) { - u8 data[2]; + static char curpage = -1; + u8 data[2], page = 0; + + /*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 (codec->hw_write(codec->control_data, data, 2) != 2){ + /*mutex_unlock(&codec->mutex);*/ + return -EIO; + } else { + curpage = page; + } + } + /* data is * D15..D8 aic3x register offset * D7...D0 register data */ - data[0] = reg & 0xff; - data[1] = value & 0xff; + data[0] = reg; + data[1] = value; if (codec->hw_write(codec->control_data, data, 2) == 2){ - aic3x_write_reg_cache(codec, data[0], data[1]); + aic3x_write_reg_cache(codec, data[0] + page * 128, data[1]); + if(!reg) curpage = value; /* for reg = 0, ie, page setting */ + /*mutex_unlock(&codec->mutex);*/ return 0; - } else + } else { + /*mutex_unlock(&codec->mutex);*/ return -EIO; + } + + return -EIO; } -/* Write a coefficient to the page 1 registers. Switching the page is - * not done here and is left to the caller. - */ -static int aic3x_write_coeff(struct snd_soc_codec *codec, unsigned int msbreg, - int value) +/* Convert a value to 2s compliment and write to registers */ +static int aic3x_write_coeff(struct snd_soc_codec *codec, + u8 msbreg, int value) { - u8 i, values[2], data[2]; u16 outp; - u16 *cache = ((struct aic3x_priv*)codec->private_data)->coeff_cache; - if (msbreg >= AIC3X_CACHEREGNUM) - return -1; - - /* Change to 2s compliment and break into MSB and LSB */ if (value < 0) outp = 65536 + value; else outp = value; - values[0] = (outp >> 8) & 0xff; - values[1] = outp & 0xff; + aic3x_write(codec, msbreg, outp >> 8); + aic3x_write(codec, msbreg+1, outp); - for(i = 0; i < 2; i++){ - data[0] = (msbreg + i) & 0xff; - data[1] = values[i] & 0xff; - - if (codec->hw_write(codec->control_data, data, 2) != 2) - return -EIO; - } - - cache[COEFF_OFFSET(msbreg)] = outp; return 0; } + /* * read from the aic3x register space */ @@ -223,23 +255,41 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, return 0; } -/* - * Reset for getting low power consumption after bypass paths - */ -static void aic3x_reset(struct snd_soc_codec *codec) +static int aic3x_sync_hw(struct snd_soc_codec *codec) { u8 *cache = codec->reg_cache; u8 data[2]; int i; - - aic3x_write(codec, AIC3X_RESET, SOFT_RESET); - + + aic3x_write(codec, AIC3X_PAGE_SELECT, 1); + /*mutex_lock(&codec->mutex);*/ + for (i = 1; i < AIC3X_PAGE1REGNUM; i++) { + data[0] = i; + data[1] = cache[i+128]; + codec->hw_write(codec->control_data, data, 2); + } + /*mutex_unlock(&codec->mutex);*/ + /* We do not rewrite page select nor reset again */ - for (i = AIC3X_SAMPLE_RATE_SEL_REG; i < ARRAY_SIZE(aic3x_reg); i++) { + aic3x_write(codec, AIC3X_PAGE_SELECT, 0); + /*mutex_lock(&codec->mutex);*/ + for (i = 2; i < AIC3X_PAGE0REGNUM; i++) { data[0] = i; data[1] = cache[i]; codec->hw_write(codec->control_data, data, 2); } + /*mutex_unlock(&codec->mutex);*/ + + return 0; +} + +/* + * Reset for getting low power consumption after bypass paths + */ +static void aic3x_reset(struct snd_soc_codec *codec) +{ + aic3x_write(codec, AIC3X_RESET, SOFT_RESET); + aic3x_sync_hw(codec); } #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ @@ -318,6 +368,8 @@ static const char *aic3x_right_hpcom_mux[] = 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[] = + { "Off", "Bass/Treble", "Custom" }; #define LDAC_ENUM 0 #define RDAC_ENUM 1 @@ -328,6 +380,7 @@ static const char *aic3x_adc_hpf[] = #define LINE2L_ENUM 6 #define LINE2R_ENUM 7 #define ADC_HPF_ENUM 8 +#define DAC_FILT_ENUM 9 static const struct soc_enum aic3x_enum[] = { SOC_ENUM_SINGLE(DAC_LINE_MUX, 6, 3, aic3x_left_dac_mux), @@ -339,6 +392,7 @@ static const struct soc_enum aic3x_enum[] = { SOC_ENUM_SINGLE(LINE2L_2_LADC_CTRL, 7, 2, aic3x_linein_mode_mux), SOC_ENUM_SINGLE(LINE2R_2_RADC_CTRL, 7, 2, aic3x_linein_mode_mux), SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 6, 4, 4, aic3x_adc_hpf), + SOC_ENUM_DOUBLE(AIC3X_CODEC_DFILT_CTRL, 1, 3, 3, aic3x_dac_filt), }; /* @@ -394,35 +448,194 @@ static int tlv320alc3x_info_volsw(struct snd_kcontrol *kcontrol, return 0; } +/* 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 snd_soc_get_3d_attenuation_aic3x(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int aic3x_dacfilter_write_coeffs + (struct snd_soc_codec *codec, struct aic3x_iir_coeffs *coeffs) +{ + printk("MNZ: dacfilter_write_coeffs\n"); + 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_D1, coeffs->D1); + aic3x_write_coeff(codec, EFFECTS_LEFT_D2, coeffs->D2); + aic3x_write_coeff(codec, EFFECTS_LEFT_N3, coeffs->N3); + aic3x_write_coeff(codec, EFFECTS_LEFT_N4, coeffs->N4); + aic3x_write_coeff(codec, EFFECTS_LEFT_N5, coeffs->N5); + aic3x_write_coeff(codec, EFFECTS_LEFT_D4, coeffs->D4); + aic3x_write_coeff(codec, EFFECTS_LEFT_D5, coeffs->D5); + + aic3x_write_coeff(codec, EFFECTS_RIGHT_N0, coeffs->N0); + aic3x_write_coeff(codec, EFFECTS_RIGHT_N1, coeffs->N1); + aic3x_write_coeff(codec, EFFECTS_RIGHT_N2, coeffs->N2); + aic3x_write_coeff(codec, EFFECTS_RIGHT_D1, coeffs->D1); + aic3x_write_coeff(codec, EFFECTS_RIGHT_D2, coeffs->D2); + aic3x_write_coeff(codec, EFFECTS_RIGHT_N3, coeffs->N3); + aic3x_write_coeff(codec, EFFECTS_RIGHT_N4, coeffs->N4); + aic3x_write_coeff(codec, EFFECTS_RIGHT_N5, coeffs->N5); + aic3x_write_coeff(codec, EFFECTS_RIGHT_D4, coeffs->D4); + aic3x_write_coeff(codec, EFFECTS_RIGHT_D5, coeffs->D5); + + 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, + sizeof(struct aic3x_iir_coeffs)); + if(aic3x->dacfilter.state == 2) + aic3x_dacfilter_set_state(codec, 0); + return 0; +} +EXPORT_SYMBOL_GPL(aic3x_dacfilter_set_coeffs); + +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; + int ret = 0; + if(aic3x->dacfilter.state == state) return 0; + + snd_soc_update_bits(codec, AIC3X_CODEC_DFILT_CTRL, + EFFECTS_ON, 0); + + if(state == 0) + ret = 1; + else if(state == 1) + ret = 1; + /* FIXME MNZ. Set preset from current chosen preset */ + 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 */ + +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) +{ + /* Only IOCTL command is for enabling/disabling filter, cmd = 1 + * arg = 0 to disable, 1 to enable and set to bass/treble, + * 2 to enable and set to custom coeffs + */ + 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)); +} + +static long snd_hwdep_dacfilter_read_aic3x(struct snd_hwdep *hw, + char __user *buf, long count, loff_t *offset) +{ + struct aic3x_priv *aic3x = + ((struct snd_soc_codec*)hw->private_data)->private_data; + if(count != sizeof(struct aic3x_iir_coeffs)) return -EINVAL; + memcpy((void*)buf, (void*)&aic3x->dacfilter.coeffs, count); + return 0; +} + +static long snd_hwdep_dacfilter_write_aic3x(struct snd_hwdep *hw, + const char __user *buf, long count, loff_t *offset) +{ + struct snd_soc_codec *codec = hw->private_data; + if(count != sizeof(struct aic3x_iir_coeffs)) return -EINVAL; + + ((struct aic3x_priv*)codec->private_data)->dacfilter.state = 2; + + return aic3x_dacfilter_set_coeffs(codec, + (struct aic3x_iir_coeffs*)buf); +} + +/* 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); + ucontrol->value.enumerated.item[0] = + ((struct aic3x_priv*)codec->private_data)->dacfilter.state; + return 0; +} + +static int snd_soc_put_dacfilter_aic3x(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { - int val = aic3x_read_coeff_cache(snd_kcontrol_chip(kcontrol), EFFECTS_3DATTEN); - if(val > 32767) - val = val - 65536; + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + if (ucontrol->value.enumerated.item[0] > 2) + return -EINVAL; + aic3x_dacfilter_set_state(codec, ucontrol->value.enumerated.item[0]); + return 1; +} + +static int snd_soc_get_3d_attenuation_aic3x + (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) +{ + int val = aic3x_read_coeff_reg_cache + (snd_kcontrol_chip(kcontrol), EFFECTS_3DATTEN); val = ((val*100)/65530) + 50; ucontrol->value.integer.value[0] = val; return 0; } -static int snd_soc_put_3d_attenuation_aic3x(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int snd_soc_put_3d_attenuation_aic3x + (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int reg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA); int val = ucontrol->value.integer.value[0]; + if(val > 100 || val < 0) return -EINVAL; if(val){ - aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, reg | 0x04); + snd_soc_update_bits(codec, AIC3X_ASD_INTF_CTRLA, + EFFECTS_3D_ON, EFFECTS_3D_ON); + val = ((val - 50) * 65535) / 100 ; } else { - aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, reg & 0xfb); + snd_soc_update_bits(codec, AIC3X_ASD_INTF_CTRLA, + EFFECTS_3D_ON, 0); + val = -32768; } - val = ((val - 50) * 65535) / 100 ; - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE1_SELECT); aic3x_write_coeff(codec, EFFECTS_3DATTEN, val); - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); return 1; } @@ -496,6 +709,9 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), + SOC_ENUM_EXT("Hardware EQ", aic3x_enum[DAC_FILT_ENUM], + snd_soc_get_dacfilter_aic3x, snd_soc_put_dacfilter_aic3x), + SOC_SINGLE_EXT("3D Control - Depth", EFFECTS_3DATTEN, 0, 100, 0, snd_soc_get_3d_attenuation_aic3x, snd_soc_put_3d_attenuation_aic3x), }; @@ -1311,39 +1527,13 @@ static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) static int aic3x_resume(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->codec; - int i; - u8 data[2]; - u8 *reg_cache = codec->reg_cache; - u16 *coeff_cache = ((struct aic3x_priv*)codec->private_data)->coeff_cache; - - /* Sync hardware with the coeff_cache first so that filters can be - * turned on safely - */ - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE1_SELECT); - for (i = 1; i < ARRAY_SIZE(aic3x_coeff); i++){ - data[0] = i*2 - 1; - data[1] = (coeff_cache[i] >> 8) && 0xff; - codec->hw_write(codec->control_data, data, 2); - - data[0]++; - data[1] = coeff_cache[i] & 0xff; - codec->hw_write(codec->control_data, data, 2); - } - - /* Sync hardware with the reg_cache */ - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); - for (i = 1; i < ARRAY_SIZE(aic3x_reg); i++) { - data[0] = i; - data[1] = reg_cache[i]; - codec->hw_write(codec->control_data, data, 2); - } - - aic3x_set_bias_level(codec, codec->suspend_bias_level); - + aic3x_sync_hw(socdev->codec); + aic3x_set_bias_level(socdev->codec, + socdev->codec->suspend_bias_level); return 0; } + /* * initialise the AIC3X driver * register the mixer and dsp interfaces with the kernel @@ -1352,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_hwdep *hwdep; + char hwdepid[] = "IIR Filter"; int reg, ret = 0; + printk("MNZ: BEGIN aic3x_init\n"); codec->name = "tlv320aic3x"; codec->owner = THIS_MODULE; codec->read = aic3x_read_reg_cache; @@ -1448,16 +1641,27 @@ static int aic3x_init(struct snd_soc_device *socdev) 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); + if (ret < 0) { printk(KERN_ERR "aic3x: failed to register card\n"); goto card_err; } /* Set some defaults for coefficients */ - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE1_SELECT); aic3x_write_coeff(codec, EFFECTS_3DATTEN, -32768); - aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); + printk("MNZ: END aic3x_init\n"); return ret; @@ -1584,7 +1788,7 @@ static int aic3x_probe(struct platform_device *pdev) return -ENOMEM; aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); - memcpy(aic3x->coeff_cache, aic3x_coeff, sizeof(aic3x_coeff)); + memcpy(&aic3x->dacfilter, &aic3x_dacfilter, sizeof(aic3x_dacfilter)); if (aic3x == NULL) { kfree(codec);