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