+WARNING: THINGS DESCRIBED BELOW ARE NOT YET IN THE REPOS. THEY WILL BE,
+VERY SOON.
+
The TLV320AIC3X is a powerful four channel low power audio codec family.
More information is available at:
http://focus.ti.com/docs/prod/folders/print/tlv320aic34.html
/ \ / \
| (N0 + 2*N1*z^-1 + N2*z^-2) || (N3 + 2*N4*z^-1 + N5*z^-2) |
| ------------------------------ || ------------------------------ |
- \ (32768 - 2*D1*z^-1 - D2*z^-2) / \ (32768 - 2*D4*z^-1 - D5*z^-2) /
+| (32768 - 2*D1*z^-1 - D2*z^-2) || (32768 - 2*D4*z^-1 - D5*z^-2) |
+\ / \ /
The filter can be controlled through an alsa hwdep device, via
-libalsa. A short example follows, note that the data struct must be
-passed *EXACTLY* as shown:
+libasound. A short example follows, note that the data struct must be
+passed *EXACTLY* as shown. Remember to link against libasound:
+gcc myapp.c -lasound -o myapp
+-------------------------------EXAMPLE----------------------------------
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <alsa/asoundlib.h>
#include <alsa/hwdep.h>
-struct _iirfilter_data {
+struct iirfilter_data {
int16_t N0, N1, N2, D1, D2;
int16_t N3, N4, N5, D4, D5;
-} iirfilter_data;
+};
-/* Initialize */
-snd_hwdep *hwdep;
+int main() {
+ int ret;
+ snd_hwdep_t *hwdep;
+ struct iirfilter_data data = {
+ .N0 = 27619, .N1 = -27034, .N2 = 26461, .D1 = 32131, .D2 = -31506,
+ .N3 = 27619, .N4 = -27034, .N5 = 26461, .D4 = 32131, .D5 = -31506
+ };
-snd_hwdep_open(&hwdep, "IIR Filter", "w");
+/* Initialize */
+ ret = snd_hwdep_open(&hwdep, "hw:0,0", SND_HWDEP_OPEN_DUPLEX);
+ if(ret != 0) exit(1);
/* To write: */
-iirfilter_data = {
- .N0 = 27619, .N1 = -27034, .N2 = 26461, .D1 = 32131, .D2 = -31506,
- .N3 = 27619, .N4 = -27034, .N5 = 26461, .D4 = 32131, .D5 = -31506
-};
-
-snd_hwdep_write(hwdep, (void*)iirfilter_data, sizeof(iirfilter_data));
+ snd_hwdep_write(hwdep, (void*)&data, sizeof(data));
/* To read: */
-snd_hwdep_read(hwdep, (void*)iirfilter_data, sizeof(iirfilter_data));
+ snd_hwdep_read(hwdep, (void*)&data, sizeof(data));
/* To enable/disable filtering: */
-int arg = 1; /* 1 = enable, 0 = disable */
-snd_hwdep_ioctl(hwdep, 1, &arg);
+ int arg = 1; /* 1 = enable, 0 = disable */
+ snd_hwdep_ioctl(hwdep, 1, &arg);
+ return 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;
}
+ 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;
} else {
curpage = page;
}
- printk("MNZ: aic3x_write(), switched to page%i\n", curpage);
}
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
int state)
{
struct aic3x_priv *aic3x = codec->private_data;
- printk("MNZ: dacfilter_set_state(state = %i)\n", state);
if(aic3x->dacfilter.state == state) return 0;
/* 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)
{
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;
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]);
{
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;
codec->name = "tlv320aic3x";
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;
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);
/* 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);