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 34MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 35MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); 36MODULE_LICENSE("GPL"); 37 38static 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 45static 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 */ 55static 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 */ 126int 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 153void 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 */ 168int 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 182static int __init alsa_ice1712_akm4xxx_module_init(void) 183{ 184 return 0; 185} 186 187static void __exit alsa_ice1712_akm4xxx_module_exit(void) 188{ 189} 190 191module_init(alsa_ice1712_akm4xxx_module_init) 192module_exit(alsa_ice1712_akm4xxx_module_exit) 193 194EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); 195EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); 196EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls); 197