]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sound/pci/spicds.c
- fix compatibility with newer versions of FreeBSD
[FreeBSD/FreeBSD.git] / sys / dev / sound / pci / spicds.c
1 /*
2  * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <dev/sound/pcm/sound.h>
30
31 #include <dev/sound/pci/ak452x.h>
32
33 MALLOC_DEFINE(M_AK452X, "ak452x", "ak452x codec");
34
35 #define AK452X_NAMELEN  16
36 struct ak452x_info {
37         device_t dev;
38         ak452x_ctrl ctrl;
39         void *devinfo;
40         int num; /* number of this device */
41         unsigned int type;   /* codec type */
42         unsigned int cif;    /* Controll data Interface Format (0/1) */
43         unsigned int format; /* data format and master clock frequency */
44         unsigned int dvc;    /* De-emphasis and Volume Control */
45         unsigned int left, right;
46         char name[AK452X_NAMELEN];
47         void *lock;
48 };
49
50 static void
51 ak452x_wrbit(struct ak452x_info *codec, int bit)
52 {
53         unsigned int cs, cdti;
54         if (codec->cif)
55                 cs = 1;
56         else
57                 cs = 0;
58         if (bit)
59                 cdti = 1;
60         else
61                 cdti = 0;
62         codec->ctrl(codec->devinfo, cs, 0, cdti);
63         DELAY(1);
64         codec->ctrl(codec->devinfo, cs, 1, cdti);
65         DELAY(1);
66
67         return;
68 }
69
70 static void
71 ak452x_wrcd(struct ak452x_info *codec, int reg, u_int8_t val)
72 {
73         int mask;
74
75 #if(0)
76         device_printf(codec->dev, "ak452x_wrcd(codec, 0x%02x, 0x%02x)\n", reg, val);
77 #endif
78         /* start */
79         if (codec->cif)
80                 codec->ctrl(codec->devinfo, 1, 1, 0);
81         else
82                 codec->ctrl(codec->devinfo, 0, 1, 0);
83         DELAY(1);
84         /* chip address */
85         ak452x_wrbit(codec, 1);
86         ak452x_wrbit(codec, 0);
87         /* write */
88         ak452x_wrbit(codec, 1);
89         /* register address */
90         for (mask = 0x10; mask != 0; mask >>= 1)
91                 ak452x_wrbit(codec, reg & mask);
92         /* data */
93         for (mask = 0x80; mask != 0; mask >>= 1)
94                 ak452x_wrbit(codec, val & mask);
95         /* stop */
96         DELAY(1);
97         if (codec->cif) {
98                 codec->ctrl(codec->devinfo, 0, 1, 0);
99                 DELAY(1);
100                 codec->ctrl(codec->devinfo, 1, 1, 0);
101         }
102         else {
103                 codec->ctrl(codec->devinfo, 1, 1, 0);
104         }
105
106         return;
107 }
108
109 struct ak452x_info *
110 ak452x_create(device_t dev, void *devinfo, int num, ak452x_ctrl ctrl)
111 {
112         struct ak452x_info *codec;
113
114 #if(0)
115         device_printf(dev, "ak452x_create(dev, devinfo, %d, ctrl)\n", num);
116 #endif
117         codec = (struct ak452x_info *)malloc(sizeof *codec, M_AK452X, M_NOWAIT);
118         if (codec == NULL)
119                 return NULL;
120
121         snprintf(codec->name, AK452X_NAMELEN, "%s:ak452x%d", device_get_nameunit(dev), num);
122         codec->lock = snd_mtxcreate(codec->name, codec->name);
123         codec->dev = dev;
124         codec->ctrl = ctrl;
125         codec->devinfo = devinfo;
126         codec->num = num;
127         codec->type = AK452X_TYPE_4524;
128         codec->cif = 0;
129         codec->format = AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X;
130         codec->dvc = AK452X_DVC_DEMOFF | AK452X_DVC_ZTM1024 | AK452X_DVC_ZCE;
131
132         return codec;
133 }
134
135 void
136 ak452x_destroy(struct ak452x_info *codec)
137 {
138         snd_mtxfree(codec->lock);
139         free(codec, M_AK452X);
140 }
141
142 void
143 ak452x_settype(struct ak452x_info *codec, unsigned int type)
144 {
145         snd_mtxlock(codec->lock);
146         codec->type = type;
147         snd_mtxunlock(codec->lock);
148 }
149
150 void
151 ak452x_setcif(struct ak452x_info *codec, unsigned int cif)
152 {
153         snd_mtxlock(codec->lock);
154         codec->cif = cif;
155         snd_mtxunlock(codec->lock);
156 }
157
158 void
159 ak452x_setformat(struct ak452x_info *codec, unsigned int format)
160 {
161         snd_mtxlock(codec->lock);
162         codec->format = format;
163         snd_mtxunlock(codec->lock);
164 }
165
166 void
167 ak452x_setdvc(struct ak452x_info *codec, unsigned int dvc)
168 {
169         snd_mtxlock(codec->lock);
170         codec->dvc = dvc;
171         snd_mtxunlock(codec->lock);
172 }
173
174 void
175 ak452x_init(struct ak452x_info *codec)
176 {
177 #if(0)
178         device_printf(codec->dev, "ak452x_init(codec)\n");
179 #endif
180         snd_mtxlock(codec->lock);
181         /* power off */
182         ak452x_wrcd(codec, AK4524_POWER, 0);
183         /* set parameter */
184         ak452x_wrcd(codec, AK4524_FORMAT, codec->format);
185         ak452x_wrcd(codec, AK4524_DVC, codec->dvc);
186         /* power on */
187         ak452x_wrcd(codec, AK4524_POWER, AK452X_POWER_PWDA | AK452X_POWER_PWAD | AK452X_POWER_PWVR);
188         /* free reset register */
189         ak452x_wrcd(codec, AK4524_RESET, AK452X_RESET_RSDA | AK452X_RESET_RSAD);
190         snd_mtxunlock(codec->lock);
191 }
192
193 void
194 ak452x_reinit(struct ak452x_info *codec)
195 {
196         snd_mtxlock(codec->lock);
197         /* reset */
198         ak452x_wrcd(codec, AK4524_RESET, 0);
199         /* set parameter */
200         ak452x_wrcd(codec, AK4524_FORMAT, codec->format);
201         ak452x_wrcd(codec, AK4524_DVC, codec->dvc);
202         /* free reset register */
203         ak452x_wrcd(codec, AK4524_RESET, AK452X_RESET_RSDA | AK452X_RESET_RSAD);
204         snd_mtxunlock(codec->lock);
205 }
206
207 void
208 ak452x_set(struct ak452x_info *codec, int dir, unsigned int left, unsigned int right)
209 {
210 #if(0)
211         device_printf(codec->dev, "ak452x_set(codec, %d, %d, %d)\n", dir, left, right);
212 #endif
213         snd_mtxlock(codec->lock);
214         if (left >= 100)
215                 left  = 127;
216         else
217                 left = left * 127 / 100;
218         if (right >= 100)
219                 right  = 127;
220         else
221                 right = right * 127 / 100;
222         if (dir == PCMDIR_REC && codec->type == AK452X_TYPE_4524) {
223 #if(0)
224                 device_printf(codec->dev, "ak452x_set(): AK4524(REC) %d/%d\n", left, right);
225 #endif
226                 ak452x_wrcd(codec, AK4524_LIPGA, left);
227                 ak452x_wrcd(codec, AK4524_RIPGA, right);
228         }
229         if (dir == PCMDIR_PLAY && codec->type == AK452X_TYPE_4524) {
230 #if(0)
231                 device_printf(codec->dev, "ak452x_set(): AK4524(PLAY) %d/%d\n", left, right);
232 #endif
233                 ak452x_wrcd(codec, AK4524_LOATT, left);
234                 ak452x_wrcd(codec, AK4524_ROATT, right);
235         }
236         if (dir == PCMDIR_PLAY && codec->type == AK452X_TYPE_4528) {
237 #if(0)
238                 device_printf(codec->dev, "ak452x_set(): AK4528(PLAY) %d/%d\n", left, right);
239 #endif
240                 ak452x_wrcd(codec, AK4528_LOATT, left);
241                 ak452x_wrcd(codec, AK4528_ROATT, right);
242         }
243         snd_mtxunlock(codec->lock);
244 }
245
246 MODULE_DEPEND(snd_ak452x, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
247 MODULE_VERSION(snd_ak452x, 1);