unsigned int sysclk;
int master;
int prepare_reset;
- u16 coeff_cache[AIC3X_COEFF_CACHE_SIZE];
};
/*
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 */
-};
-
/*
* read aic3x register cache
*/
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)];
-}
-
/*
* write aic3x register cache
*/
data[0] = reg & 0xff;
data[1] = value & 0xff;
- 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], data[1]);
+ if (codec->hw_write(codec->control_data, data, 2) == 2)
return 0;
- } else
+ else
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)
-{
- 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;
-
- 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
*/
return 0;
}
-
-static int snd_soc_get_3d_attenuation_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;
- 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)
-{
- 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){
- aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, reg | 0x04);
- } else {
- aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, reg & 0xfb);
- }
-
- 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;
-}
-
static const struct snd_kcontrol_new aic3x_snd_controls[] = {
/* Output */
SOC_DOUBLE_R_TLV("PCM Playback Volume",
SOC_DOUBLE_R("PGA Capture Switch", LADC_VOL, RADC_VOL, 7, 0x01, 1),
SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
-
- SOC_SINGLE_EXT("3D Control - Depth", EFFECTS_3DATTEN, 0, 100, 0,
- snd_soc_get_3d_attenuation_aic3x, snd_soc_put_3d_attenuation_aic3x),
};
/* add non dapm controls */
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);
- }
+ u8 *cache = codec->reg_cache;
- /* Sync hardware with the reg_cache */
- aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
- for (i = 1; i < ARRAY_SIZE(aic3x_reg); i++) {
+ /* Sync reg_cache with the hardware */
+ for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) {
data[0] = i;
- data[1] = reg_cache[i];
+ data[1] = cache[i];
codec->hw_write(codec->control_data, data, 2);
}
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);
-
return ret;
card_err:
return -ENOMEM;
aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
- memcpy(aic3x->coeff_cache, aic3x_coeff, sizeof(aic3x_coeff));
-
if (aic3x == NULL) {
kfree(codec);
return -ENOMEM;
/* AIC3X register space */
#define AIC3X_CACHEREGNUM 103
-#define AIC3X_COEFF_CACHE_SIZE 52
-#define COEFF_OFFSET(msbreg) ((msbreg+1)/2)
/* Page select register */
#define AIC3X_PAGE_SELECT 0
/* Clock generation control register */
#define AIC3X_CLKGEN_CTRL_REG 102
-/* Page 1 registers for setting coefficients for filters */
-/* DAC Audio Effects for Left Channel */
-#define EFFECTS_LEFT_N0 1
-#define EFFECTS_LEFT_N1 3
-#define EFFECTS_LEFT_N2 5
-#define EFFECTS_LEFT_N3 7
-#define EFFECTS_LEFT_N4 9
-#define EFFECTS_LEFT_N5 11
-
-#define EFFECTS_LEFT_D1 13
-#define EFFECTS_LEFT_D2 15
-#define EFFECTS_LEFT_D4 17
-#define EFFECTS_LEFT_D5 19
-
-/* DAC De-Emphasis for Left Channel */
-
-#define DEEMPH_LEFT_N0 21
-#define DEEMPH_LEFT_N1 23
-#define DEEMPH_LEFT_D1 25
-
-/* DAC Audio Effects for Right Channel */
-
-#define EFFECTS_RIGHT_N0 27
-#define EFFECTS_RIGHT_N1 29
-#define EFFECTS_RIGHT_N2 31
-#define EFFECTS_RIGHT_N3 33
-#define EFFECTS_RIGHT_N4 35
-#define EFFECTS_RIGHT_N5 37
-
-#define EFFECTS_RIGHT_D1 39
-#define EFFECTS_RIGHT_D2 41
-#define EFFECTS_RIGHT_D4 43
-#define EFFECTS_RIGHT_D5 45
-
-/* DAC De-Emphasis for Right Channel */
-
-#define DEEMPH_RIGHT_N0 47
-#define DEEMPH_RIGHT_N1 49
-#define DEEMPH_RIGHT_D1 51
-
-/* DAC 3D Attenuation */
-
-#define EFFECTS_3DATTEN 53
-
-/* ADC High-Pass Filter for Left Channel */
-
-#define HIGHPASS_LEFT_NO 65
-#define HIGHPASS_LEFT_N1 67
-#define HIGHPASS_LEFT_D1 69
-
-/* ADC High-Pass Filter for Right Channel */
-
-#define HIGHPASS_RIGHT_NO 71
-#define HIGHPASS_RIGHT_N1 73
-#define HIGHPASS_RIGHT_D1 75
-
/* Page select register bits */
#define PAGE0_SELECT 0
#define PAGE1_SELECT 1