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/init.h> 28 #include <sound/core.h> 29 #include <sound/initval.h> 30 #include "ice1712.h" 31 32 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 33 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); 34 MODULE_LICENSE("GPL"); 35 36 static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip) 37 { 38 struct snd_ice1712 *ice = ak->private_data[0]; 39 40 snd_ice1712_save_gpio_status(ice); 41 } 42 43 static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip) 44 { 45 struct snd_ice1712 *ice = ak->private_data[0]; 46 47 snd_ice1712_restore_gpio_status(ice); 48 } 49 50 /* 51 * write AK4xxx register 52 */ 53 static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip, 54 unsigned char addr, unsigned char data) 55 { 56 unsigned int tmp; 57 int idx; 58 unsigned int addrdata; 59 struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; 60 struct snd_ice1712 *ice = ak->private_data[0]; 61 62 snd_assert(chip >= 0 && chip < 4, return); 63 64 tmp = snd_ice1712_gpio_read(ice); 65 tmp |= priv->add_flags; 66 tmp &= ~priv->mask_flags; 67 if (priv->cs_mask == priv->cs_addr) { 68 if (priv->cif) { 69 tmp |= priv->cs_mask; /* start without chip select */ 70 } else { 71 tmp &= ~priv->cs_mask; /* chip select low */ 72 snd_ice1712_gpio_write(ice, tmp); 73 udelay(1); 74 } 75 } else { 76 /* doesn't handle cf=1 yet */ 77 tmp &= ~priv->cs_mask; 78 tmp |= priv->cs_addr; 79 snd_ice1712_gpio_write(ice, tmp); 80 udelay(1); 81 } 82 83 /* build I2C address + data byte */ 84 addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f); 85 addrdata = (addrdata << 8) | data; 86 for (idx = 15; idx >= 0; idx--) { 87 /* drop clock */ 88 tmp &= ~priv->clk_mask; 89 snd_ice1712_gpio_write(ice, tmp); 90 udelay(1); 91 /* set data */ 92 if (addrdata & (1 << idx)) 93 tmp |= priv->data_mask; 94 else 95 tmp &= ~priv->data_mask; 96 snd_ice1712_gpio_write(ice, tmp); 97 udelay(1); 98 /* raise clock */ 99 tmp |= priv->clk_mask; 100 snd_ice1712_gpio_write(ice, tmp); 101 udelay(1); 102 } 103 104 if (priv->cs_mask == priv->cs_addr) { 105 if (priv->cif) { 106 /* assert a cs pulse to trigger */ 107 tmp &= ~priv->cs_mask; 108 snd_ice1712_gpio_write(ice, tmp); 109 udelay(1); 110 } 111 tmp |= priv->cs_mask; /* chip select high to trigger */ 112 } else { 113 tmp &= ~priv->cs_mask; 114 tmp |= priv->cs_none; /* deselect address */ 115 } 116 snd_ice1712_gpio_write(ice, tmp); 117 udelay(1); 118 } 119 120 /* 121 * initialize the struct snd_akm4xxx record with the template 122 */ 123 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp, 124 const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice) 125 { 126 struct snd_ak4xxx_private *priv; 127 128 if (_priv != NULL) { 129 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 130 if (priv == NULL) 131 return -ENOMEM; 132 *priv = *_priv; 133 } else { 134 priv = NULL; 135 } 136 *ak = *temp; 137 ak->card = ice->card; 138 ak->private_value[0] = (unsigned long)priv; 139 ak->private_data[0] = ice; 140 if (ak->ops.lock == NULL) 141 ak->ops.lock = snd_ice1712_akm4xxx_lock; 142 if (ak->ops.unlock == NULL) 143 ak->ops.unlock = snd_ice1712_akm4xxx_unlock; 144 if (ak->ops.write == NULL) 145 ak->ops.write = snd_ice1712_akm4xxx_write; 146 snd_akm4xxx_init(ak); 147 return 0; 148 } 149 150 void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice) 151 { 152 unsigned int akidx; 153 if (ice->akm == NULL) 154 return; 155 for (akidx = 0; akidx < ice->akm_codecs; akidx++) { 156 struct snd_akm4xxx *ak = &ice->akm[akidx]; 157 kfree((void*)ak->private_value[0]); 158 } 159 kfree(ice->akm); 160 } 161 162 /* 163 * build AK4xxx controls 164 */ 165 int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice) 166 { 167 unsigned int akidx; 168 int err; 169 170 for (akidx = 0; akidx < ice->akm_codecs; akidx++) { 171 struct snd_akm4xxx *ak = &ice->akm[akidx]; 172 err = snd_akm4xxx_build_controls(ak); 173 if (err < 0) 174 return err; 175 } 176 return 0; 177 } 178 179 static int __init alsa_ice1712_akm4xxx_module_init(void) 180 { 181 return 0; 182 } 183 184 static void __exit alsa_ice1712_akm4xxx_module_exit(void) 185 { 186 } 187 188 module_init(alsa_ice1712_akm4xxx_module_init) 189 module_exit(alsa_ice1712_akm4xxx_module_exit) 190 191 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); 192 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); 193 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls); 194