1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* 1 /* 3 * ALSA driver for ICEnsemble ICE1712 (Envy2 2 * ALSA driver for ICEnsemble ICE1712 (Envy24) 4 * 3 * 5 * AK4524 / AK4528 / AK4529 / AK4355 / AK438 4 * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface 6 * 5 * 7 * Copyright (c) 2000 Jaroslav Kysela <pe 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 * 8 */ 22 */ 9 23 10 #include <linux/io.h> 24 #include <linux/io.h> 11 #include <linux/delay.h> 25 #include <linux/delay.h> 12 #include <linux/interrupt.h> 26 #include <linux/interrupt.h> 13 #include <linux/slab.h> 27 #include <linux/slab.h> 14 #include <linux/init.h> 28 #include <linux/init.h> 15 #include <linux/module.h> 29 #include <linux/module.h> 16 #include <sound/core.h> 30 #include <sound/core.h> 17 #include <sound/initval.h> 31 #include <sound/initval.h> 18 #include "ice1712.h" 32 #include "ice1712.h" 19 33 20 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz 34 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 21 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4 35 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface"); 22 MODULE_LICENSE("GPL"); 36 MODULE_LICENSE("GPL"); 23 37 24 static void snd_ice1712_akm4xxx_lock(struct sn 38 static void snd_ice1712_akm4xxx_lock(struct snd_akm4xxx *ak, int chip) 25 { 39 { 26 struct snd_ice1712 *ice = ak->private_ 40 struct snd_ice1712 *ice = ak->private_data[0]; 27 41 28 snd_ice1712_save_gpio_status(ice); 42 snd_ice1712_save_gpio_status(ice); 29 } 43 } 30 44 31 static void snd_ice1712_akm4xxx_unlock(struct 45 static void snd_ice1712_akm4xxx_unlock(struct snd_akm4xxx *ak, int chip) 32 { 46 { 33 struct snd_ice1712 *ice = ak->private_ 47 struct snd_ice1712 *ice = ak->private_data[0]; 34 48 35 snd_ice1712_restore_gpio_status(ice); 49 snd_ice1712_restore_gpio_status(ice); 36 } 50 } 37 51 38 /* 52 /* 39 * write AK4xxx register 53 * write AK4xxx register 40 */ 54 */ 41 static void snd_ice1712_akm4xxx_write(struct s 55 static void snd_ice1712_akm4xxx_write(struct snd_akm4xxx *ak, int chip, 42 unsigned 56 unsigned char addr, unsigned char data) 43 { 57 { 44 unsigned int tmp; 58 unsigned int tmp; 45 int idx; 59 int idx; 46 unsigned int addrdata; 60 unsigned int addrdata; 47 struct snd_ak4xxx_private *priv = (voi 61 struct snd_ak4xxx_private *priv = (void *)ak->private_value[0]; 48 struct snd_ice1712 *ice = ak->private_ 62 struct snd_ice1712 *ice = ak->private_data[0]; 49 63 50 if (snd_BUG_ON(chip < 0 || chip >= 4)) 64 if (snd_BUG_ON(chip < 0 || chip >= 4)) 51 return; 65 return; 52 66 53 tmp = snd_ice1712_gpio_read(ice); 67 tmp = snd_ice1712_gpio_read(ice); 54 tmp |= priv->add_flags; 68 tmp |= priv->add_flags; 55 tmp &= ~priv->mask_flags; 69 tmp &= ~priv->mask_flags; 56 if (priv->cs_mask == priv->cs_addr) { 70 if (priv->cs_mask == priv->cs_addr) { 57 if (priv->cif) { 71 if (priv->cif) { 58 tmp |= priv->cs_mask; 72 tmp |= priv->cs_mask; /* start without chip select */ 59 } else { 73 } else { 60 tmp &= ~priv->cs_mask; 74 tmp &= ~priv->cs_mask; /* chip select low */ 61 snd_ice1712_gpio_write 75 snd_ice1712_gpio_write(ice, tmp); 62 udelay(1); 76 udelay(1); 63 } 77 } 64 } else { 78 } else { 65 /* doesn't handle cf=1 yet */ 79 /* doesn't handle cf=1 yet */ 66 tmp &= ~priv->cs_mask; 80 tmp &= ~priv->cs_mask; 67 tmp |= priv->cs_addr; 81 tmp |= priv->cs_addr; 68 snd_ice1712_gpio_write(ice, tm 82 snd_ice1712_gpio_write(ice, tmp); 69 udelay(1); 83 udelay(1); 70 } 84 } 71 85 72 /* build I2C address + data byte */ 86 /* build I2C address + data byte */ 73 addrdata = (priv->caddr << 6) | 0x20 | 87 addrdata = (priv->caddr << 6) | 0x20 | (addr & 0x1f); 74 addrdata = (addrdata << 8) | data; 88 addrdata = (addrdata << 8) | data; 75 for (idx = 15; idx >= 0; idx--) { 89 for (idx = 15; idx >= 0; idx--) { 76 /* drop clock */ 90 /* drop clock */ 77 tmp &= ~priv->clk_mask; 91 tmp &= ~priv->clk_mask; 78 snd_ice1712_gpio_write(ice, tm 92 snd_ice1712_gpio_write(ice, tmp); 79 udelay(1); 93 udelay(1); 80 /* set data */ 94 /* set data */ 81 if (addrdata & (1 << idx)) 95 if (addrdata & (1 << idx)) 82 tmp |= priv->data_mask 96 tmp |= priv->data_mask; 83 else 97 else 84 tmp &= ~priv->data_mas 98 tmp &= ~priv->data_mask; 85 snd_ice1712_gpio_write(ice, tm 99 snd_ice1712_gpio_write(ice, tmp); 86 udelay(1); 100 udelay(1); 87 /* raise clock */ 101 /* raise clock */ 88 tmp |= priv->clk_mask; 102 tmp |= priv->clk_mask; 89 snd_ice1712_gpio_write(ice, tm 103 snd_ice1712_gpio_write(ice, tmp); 90 udelay(1); 104 udelay(1); 91 } 105 } 92 106 93 if (priv->cs_mask == priv->cs_addr) { 107 if (priv->cs_mask == priv->cs_addr) { 94 if (priv->cif) { 108 if (priv->cif) { 95 /* assert a cs pulse t 109 /* assert a cs pulse to trigger */ 96 tmp &= ~priv->cs_mask; 110 tmp &= ~priv->cs_mask; 97 snd_ice1712_gpio_write 111 snd_ice1712_gpio_write(ice, tmp); 98 udelay(1); 112 udelay(1); 99 } 113 } 100 tmp |= priv->cs_mask; /* chip 114 tmp |= priv->cs_mask; /* chip select high to trigger */ 101 } else { 115 } else { 102 tmp &= ~priv->cs_mask; 116 tmp &= ~priv->cs_mask; 103 tmp |= priv->cs_none; /* desel 117 tmp |= priv->cs_none; /* deselect address */ 104 } 118 } 105 snd_ice1712_gpio_write(ice, tmp); 119 snd_ice1712_gpio_write(ice, tmp); 106 udelay(1); 120 udelay(1); 107 } 121 } 108 122 109 /* 123 /* 110 * initialize the struct snd_akm4xxx record wi 124 * initialize the struct snd_akm4xxx record with the template 111 */ 125 */ 112 int snd_ice1712_akm4xxx_init(struct snd_akm4xx 126 int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *temp, 113 const struct snd_ 127 const struct snd_ak4xxx_private *_priv, struct snd_ice1712 *ice) 114 { 128 { 115 struct snd_ak4xxx_private *priv; 129 struct snd_ak4xxx_private *priv; 116 130 117 if (_priv != NULL) { 131 if (_priv != NULL) { 118 priv = kmalloc(sizeof(*priv), 132 priv = kmalloc(sizeof(*priv), GFP_KERNEL); 119 if (priv == NULL) 133 if (priv == NULL) 120 return -ENOMEM; 134 return -ENOMEM; 121 *priv = *_priv; 135 *priv = *_priv; 122 } else { 136 } else { 123 priv = NULL; 137 priv = NULL; 124 } 138 } 125 *ak = *temp; 139 *ak = *temp; 126 ak->card = ice->card; 140 ak->card = ice->card; 127 ak->private_value[0] = (unsigned long) 141 ak->private_value[0] = (unsigned long)priv; 128 ak->private_data[0] = ice; 142 ak->private_data[0] = ice; 129 if (ak->ops.lock == NULL) 143 if (ak->ops.lock == NULL) 130 ak->ops.lock = snd_ice1712_akm 144 ak->ops.lock = snd_ice1712_akm4xxx_lock; 131 if (ak->ops.unlock == NULL) 145 if (ak->ops.unlock == NULL) 132 ak->ops.unlock = snd_ice1712_a 146 ak->ops.unlock = snd_ice1712_akm4xxx_unlock; 133 if (ak->ops.write == NULL) 147 if (ak->ops.write == NULL) 134 ak->ops.write = snd_ice1712_ak 148 ak->ops.write = snd_ice1712_akm4xxx_write; 135 snd_akm4xxx_init(ak); 149 snd_akm4xxx_init(ak); 136 return 0; 150 return 0; 137 } 151 } 138 152 139 void snd_ice1712_akm4xxx_free(struct snd_ice17 153 void snd_ice1712_akm4xxx_free(struct snd_ice1712 *ice) 140 { 154 { 141 unsigned int akidx; 155 unsigned int akidx; 142 if (ice->akm == NULL) 156 if (ice->akm == NULL) 143 return; 157 return; 144 for (akidx = 0; akidx < ice->akm_codec 158 for (akidx = 0; akidx < ice->akm_codecs; akidx++) { 145 struct snd_akm4xxx *ak = &ice- 159 struct snd_akm4xxx *ak = &ice->akm[akidx]; 146 kfree((void*)ak->private_value 160 kfree((void*)ak->private_value[0]); 147 } 161 } 148 kfree(ice->akm); 162 kfree(ice->akm); 149 } 163 } 150 164 151 /* 165 /* 152 * build AK4xxx controls 166 * build AK4xxx controls 153 */ 167 */ 154 int snd_ice1712_akm4xxx_build_controls(struct 168 int snd_ice1712_akm4xxx_build_controls(struct snd_ice1712 *ice) 155 { 169 { 156 unsigned int akidx; 170 unsigned int akidx; 157 int err; 171 int err; 158 172 159 for (akidx = 0; akidx < ice->akm_codec 173 for (akidx = 0; akidx < ice->akm_codecs; akidx++) { 160 struct snd_akm4xxx *ak = &ice- 174 struct snd_akm4xxx *ak = &ice->akm[akidx]; 161 err = snd_akm4xxx_build_contro 175 err = snd_akm4xxx_build_controls(ak); 162 if (err < 0) 176 if (err < 0) 163 return err; 177 return err; 164 } 178 } 165 return 0; 179 return 0; 166 } 180 } >> 181 >> 182 static int __init alsa_ice1712_akm4xxx_module_init(void) >> 183 { >> 184 return 0; >> 185 } >> 186 >> 187 static void __exit alsa_ice1712_akm4xxx_module_exit(void) >> 188 { >> 189 } >> 190 >> 191 module_init(alsa_ice1712_akm4xxx_module_init) >> 192 module_exit(alsa_ice1712_akm4xxx_module_exit) 167 193 168 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); 194 EXPORT_SYMBOL(snd_ice1712_akm4xxx_init); 169 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); 195 EXPORT_SYMBOL(snd_ice1712_akm4xxx_free); 170 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_contro 196 EXPORT_SYMBOL(snd_ice1712_akm4xxx_build_controls); 171 197
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.