1 /* 2 * ALSA driver for ICEnsemble ICE1712 (Envy24) 3 * 4 * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface 5 * 6 * Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24 #include <asm/io.h> 25 #include <linux/delay.h> 26 #include <linux/interrupt.h> 27 #include <linux/slab.h> 28 #include <linux/init.h> 29 #include <sound/core.h> 30 #include <sound/initval.h> 31 #include "ice1712.h" 32 33 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 34 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); 35 MODULE_LICENSE("GPL"); 36 37 static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip) 38 { 39 struct snd_ice1712 *ice = ak->private_data[0]; 40 41 snd_ice1712_save_gpio_status(ice); 42 } 43 44 static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip) 45 { 46 struct snd_ice1712 *ice = ak->private_data[0]; 47 48 snd_ice1712_restore_gpio_status(ice); 49 } 50 51 /* 52 * write AK4xxx register 53 */ 54 static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip, 55 unsigned char addr, unsigned char data) 56 { 57 unsigned int tmp; 58 int idx; 59 unsigned int addrdata; 60 struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; 61 struct snd_ice1712 *ice = ak->private_data[0]; 62 63 if (snd_BUG_ON(chip < 0 || chip >= 4)) 64 return; 65 66 tmp = snd_ice1712_gpio_read(ice); 67 tmp |= priv->add_flags; 68 tmp &= ~priv->mask_flags; 69 if (priv->cs_mask == priv->cs_addr) { 70 if (priv->cif) { 71 tmp |= priv->cs_mask; /* start without chip select */ 72 } else { 73 tmp &= ~priv->cs_mask; /* chip select low */ 74 snd_ice1712_gpio_write(ice, tmp); 75 udelay(1); 76 } 77 } else { 78 /* doesn't handle cf=1 yet */ 79 tmp &= ~priv->cs_mask; 80 tmp |= priv->cs_addr; 81 snd_ice1712_gpio_write(ice, tmp); 82 udelay(1); 83 } 84 85 /* build I2C address + data byte */ 86 addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f); 87 addrdata = (addrdata << 8) | data; 88 for (idx = 15; idx >= 0; idx--) { 89 /* drop clock */ 90 tmp &= ~priv->clk_mask; 91 snd_ice1712_gpio_write(ice, tmp); 92 udelay(1); 93 /* set data */ 94 if (addrdata & (1 << idx)) 95 tmp |= priv->data_mask; 96 else 97 tmp &= ~priv->data_mask; 98 snd_ice1712_gpio_write(ice, tmp); 99 udelay(1); 100 /* raise clock */ 101 tmp |= priv->clk_mask; 102 snd_ice1712_gpio_write(ice, tmp); 103 udelay(1); 104 } 105 106 if (priv->cs_mask == priv->cs_addr) { 107 if (priv->cif) { 108 /* assert a cs pulse to trigger */ 109 tmp &= ~priv->cs_mask; 110 snd_ice1712_gpio_write(ice, tmp); 111 udelay(1); 112 } 113 tmp |= priv->cs_mask; /* chip select high to trigger */ 114 } else { 115 tmp &= ~priv->cs_mask; 116 tmp |= priv->cs_none; /* deselect address */ 117 } 118 snd_ice1712_gpio_write(ice, tmp); 119 udelay(1); 120 } 121 122 /* 123 * initialize the struct snd_akm4xxx record with the template 124 */ 125 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp, 126 const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice) 127 { 128 struct snd_ak4xxx_private *priv; 129 130 if (_priv != NULL) { 131 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 132 if (priv == NULL) 133 return -ENOMEM; 134 *priv = *_priv; 135 } else { 136 priv = NULL; 137 } 138 *ak = *temp; 139 ak->card = ice->card; 140 ak->private_value[0] = (unsigned long)priv; 141 ak->private_data[0] = ice; 142 if (ak->ops.lock == NULL) 143 ak->ops.lock = snd_ice1712_akm4xxx_lock; 144 if (ak->ops.unlock == NULL) 145 ak->ops.unlock = snd_ice1712_akm4xxx_unlock; 146 if (ak->ops.write == NULL) 147 ak->ops.write = snd_ice1712_akm4xxx_write; 148 snd_akm4xxx_init(ak); 149 return 0; 150 } 151 152 void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice) 153 { 154 unsigned int akidx; 155 if (ice->akm == NULL) 156 return; 157 for (akidx = 0; akidx < ice->akm_codecs; akidx++) { 158 struct snd_akm4xxx *ak = &ice->akm[akidx]; 159 kfree((void*)ak->private_value[0]); 160 } 161 kfree(ice->akm); 162 } 163 164 /* 165 * build AK4xxx controls 166 */ 167 int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice) 168 { 169 unsigned int akidx; 170 int err; 171 172 for (akidx = 0; akidx < ice->akm_codecs; akidx++) { 173 struct snd_akm4xxx *ak = &ice->akm[akidx]; 174 err = snd_akm4xxx_build_controls(ak); 175 if (err < 0) 176 return err; 177 } 178 return 0; 179 } 180 181 static int __init alsa_ice1712_akm4xxx_module_init(void) 182 { 183 return 0; 184 } 185 186 static void __exit alsa_ice1712_akm4xxx_module_exit(void) 187 { 188 } 189 190 module_init(alsa_ice1712_akm4xxx_module_init) 191 module_exit(alsa_ice1712_akm4xxx_module_exit) 192 193 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); 194 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); 195 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls); 196