📄 ak4xxx.c
字号:
/* * ALSA driver for ICEnsemble ICE1712 (Envy24) * * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface * * Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include <sound/driver.h>#include <asm/io.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/init.h>#include <sound/core.h>#include <sound/initval.h>#include "ice1712.h"MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");MODULE_LICENSE("GPL");static void snd_ice1712_akm4xxx_lock(akm4xxx_t *ak, int chip){ ice1712_t *ice = ak->private_data[0]; snd_ice1712_save_gpio_status(ice);}static void snd_ice1712_akm4xxx_unlock(akm4xxx_t *ak, int chip){ ice1712_t *ice = ak->private_data[0]; snd_ice1712_restore_gpio_status(ice);}/* * write AK4xxx register */static void snd_ice1712_akm4xxx_write(akm4xxx_t *ak, int chip, unsigned char addr, unsigned char data){ unsigned int tmp; int idx; unsigned int addrdata; struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; ice1712_t *ice = ak->private_data[0]; snd_assert(chip >= 0 && chip < 4, return); tmp = snd_ice1712_gpio_read(ice); tmp |= priv->add_flags; tmp &= ~priv->mask_flags; if (priv->cs_mask == priv->cs_addr) { if (priv->cif) { tmp |= priv->cs_mask; /* start without chip select */ } else { tmp &= ~priv->cs_mask; /* chip select low */ snd_ice1712_gpio_write(ice, tmp); udelay(1); } } else { /* doesn't handle cf=1 yet */ tmp &= ~priv->cs_mask; tmp |= priv->cs_addr; snd_ice1712_gpio_write(ice, tmp); udelay(1); } /* build I2C address + data byte */ addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f); addrdata = (addrdata << 8) | data; for (idx = 15; idx >= 0; idx--) { /* drop clock */ tmp &= ~priv->clk_mask; snd_ice1712_gpio_write(ice, tmp); udelay(1); /* set data */ if (addrdata & (1 << idx)) tmp |= priv->data_mask; else tmp &= ~priv->data_mask; snd_ice1712_gpio_write(ice, tmp); udelay(1); /* raise clock */ tmp |= priv->clk_mask; snd_ice1712_gpio_write(ice, tmp); udelay(1); } if (priv->cs_mask == priv->cs_addr) { if (priv->cif) { /* assert a cs pulse to trigger */ tmp &= ~priv->cs_mask; snd_ice1712_gpio_write(ice, tmp); udelay(1); } tmp |= priv->cs_mask; /* chip select high to trigger */ } else { tmp &= ~priv->cs_mask; tmp |= priv->cs_none; /* deselect address */ } snd_ice1712_gpio_write(ice, tmp); udelay(1);}/* * initialize the akm4xxx_t record with the template */int snd_ice1712_akm4xxx_init(akm4xxx_t *ak, const akm4xxx_t *temp, const struct snd_ak4xxx_private *_priv, ice1712_t *ice){ struct snd_ak4xxx_private *priv; if (_priv != NULL) { priv = kmalloc(sizeof(*priv), GFP_KERNEL); if (priv == NULL) return -ENOMEM; *priv = *_priv; } else { priv = NULL; } *ak = *temp; ak->card = ice->card; ak->private_value[0] = (unsigned long)priv; ak->private_data[0] = ice; if (ak->ops.lock == NULL) ak->ops.lock = snd_ice1712_akm4xxx_lock; if (ak->ops.unlock == NULL) ak->ops.unlock = snd_ice1712_akm4xxx_unlock; if (ak->ops.write == NULL) ak->ops.write = snd_ice1712_akm4xxx_write; snd_akm4xxx_init(ak); return 0;}void snd_ice1712_akm4xxx_free(ice1712_t *ice){ unsigned int akidx; if (ice->akm == NULL) return; for (akidx = 0; akidx < ice->akm_codecs; akidx++) { akm4xxx_t *ak = &ice->akm[akidx]; kfree((void*)ak->private_value[0]); } kfree(ice->akm);}/* * build AK4xxx controls */int snd_ice1712_akm4xxx_build_controls(ice1712_t *ice){ unsigned int akidx; int err; for (akidx = 0; akidx < ice->akm_codecs; akidx++) { akm4xxx_t *ak = &ice->akm[akidx]; err = snd_akm4xxx_build_controls(ak); if (err < 0) return err; } return 0;}static int __init alsa_ice1712_akm4xxx_module_init(void){ return 0;} static void __exit alsa_ice1712_akm4xxx_module_exit(void){} module_init(alsa_ice1712_akm4xxx_module_init)module_exit(alsa_ice1712_akm4xxx_module_exit)EXPORT_SYMBOL(snd_ice1712_akm4xxx_init);EXPORT_SYMBOL(snd_ice1712_akm4xxx_free);EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -