Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ak4xxx.c
Go to the documentation of this file.
1 /*
2  * ALSA driver for ICEnsemble ICE1712 (Envy24)
3  *
4  * AK4524 / AK4528 / AK4529 / AK4355 / AK4381 interface
5  *
6  * Copyright (c) 2000 Jaroslav Kysela <[email protected]>
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/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 <[email protected]>");
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 
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 
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  */
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 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)
193