0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/io.h>
0011 #include <linux/delay.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/slab.h>
0014 #include <linux/init.h>
0015 #include <linux/module.h>
0016 #include <sound/core.h>
0017 #include <sound/initval.h>
0018 #include "ice1712.h"
0019
0020 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0021 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
0022 MODULE_LICENSE("GPL");
0023
0024 static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip)
0025 {
0026 struct snd_ice1712 *ice = ak->private_data[0];
0027
0028 snd_ice1712_save_gpio_status(ice);
0029 }
0030
0031 static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip)
0032 {
0033 struct snd_ice1712 *ice = ak->private_data[0];
0034
0035 snd_ice1712_restore_gpio_status(ice);
0036 }
0037
0038
0039
0040
0041 static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip,
0042 unsigned char addr, unsigned char data)
0043 {
0044 unsigned int tmp;
0045 int idx;
0046 unsigned int addrdata;
0047 struct snd_ak4xxx_private *priv = (void *)ak->private_value[0];
0048 struct snd_ice1712 *ice = ak->private_data[0];
0049
0050 if (snd_BUG_ON(chip < 0 || chip >= 4))
0051 return;
0052
0053 tmp = snd_ice1712_gpio_read(ice);
0054 tmp |= priv->add_flags;
0055 tmp &= ~priv->mask_flags;
0056 if (priv->cs_mask == priv->cs_addr) {
0057 if (priv->cif) {
0058 tmp |= priv->cs_mask;
0059 } else {
0060 tmp &= ~priv->cs_mask;
0061 snd_ice1712_gpio_write(ice, tmp);
0062 udelay(1);
0063 }
0064 } else {
0065
0066 tmp &= ~priv->cs_mask;
0067 tmp |= priv->cs_addr;
0068 snd_ice1712_gpio_write(ice, tmp);
0069 udelay(1);
0070 }
0071
0072
0073 addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f);
0074 addrdata = (addrdata << 8) | data;
0075 for (idx = 15; idx >= 0; idx--) {
0076
0077 tmp &= ~priv->clk_mask;
0078 snd_ice1712_gpio_write(ice, tmp);
0079 udelay(1);
0080
0081 if (addrdata & (1 << idx))
0082 tmp |= priv->data_mask;
0083 else
0084 tmp &= ~priv->data_mask;
0085 snd_ice1712_gpio_write(ice, tmp);
0086 udelay(1);
0087
0088 tmp |= priv->clk_mask;
0089 snd_ice1712_gpio_write(ice, tmp);
0090 udelay(1);
0091 }
0092
0093 if (priv->cs_mask == priv->cs_addr) {
0094 if (priv->cif) {
0095
0096 tmp &= ~priv->cs_mask;
0097 snd_ice1712_gpio_write(ice, tmp);
0098 udelay(1);
0099 }
0100 tmp |= priv->cs_mask;
0101 } else {
0102 tmp &= ~priv->cs_mask;
0103 tmp |= priv->cs_none;
0104 }
0105 snd_ice1712_gpio_write(ice, tmp);
0106 udelay(1);
0107 }
0108
0109
0110
0111
0112 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp,
0113 const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice)
0114 {
0115 struct snd_ak4xxx_private *priv;
0116
0117 if (_priv != NULL) {
0118 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
0119 if (priv == NULL)
0120 return -ENOMEM;
0121 *priv = *_priv;
0122 } else {
0123 priv = NULL;
0124 }
0125 *ak = *temp;
0126 ak->card = ice->card;
0127 ak->private_value[0] = (unsigned long)priv;
0128 ak->private_data[0] = ice;
0129 if (ak->ops.lock == NULL)
0130 ak->ops.lock = snd_ice1712_akm4xxx_lock;
0131 if (ak->ops.unlock == NULL)
0132 ak->ops.unlock = snd_ice1712_akm4xxx_unlock;
0133 if (ak->ops.write == NULL)
0134 ak->ops.write = snd_ice1712_akm4xxx_write;
0135 snd_akm4xxx_init(ak);
0136 return 0;
0137 }
0138
0139 void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice)
0140 {
0141 unsigned int akidx;
0142 if (ice->akm == NULL)
0143 return;
0144 for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
0145 struct snd_akm4xxx *ak = &ice->akm[akidx];
0146 kfree((void*)ak->private_value[0]);
0147 }
0148 kfree(ice->akm);
0149 }
0150
0151
0152
0153
0154 int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice)
0155 {
0156 unsigned int akidx;
0157 int err;
0158
0159 for (akidx = 0; akidx < ice->akm_codecs; akidx++) {
0160 struct snd_akm4xxx *ak = &ice->akm[akidx];
0161 err = snd_akm4xxx_build_controls(ak);
0162 if (err < 0)
0163 return err;
0164 }
0165 return 0;
0166 }
0167
0168 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init);
0169 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free);
0170 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls);