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