2 * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include <dev/sound/pcm/sound.h>
31 #include <dev/sound/pci/ak452x.h>
33 MALLOC_DEFINE(M_AK452X, "ak452x", "ak452x codec");
35 #define AK452X_NAMELEN 16
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];
51 ak452x_wrbit(struct ak452x_info *codec, int bit)
53 unsigned int cs, cdti;
62 codec->ctrl(codec->devinfo, cs, 0, cdti);
64 codec->ctrl(codec->devinfo, cs, 1, cdti);
71 ak452x_wrcd(struct ak452x_info *codec, int reg, u_int8_t val)
76 device_printf(codec->dev, "ak452x_wrcd(codec, 0x%02x, 0x%02x)\n", reg, val);
80 codec->ctrl(codec->devinfo, 1, 1, 0);
82 codec->ctrl(codec->devinfo, 0, 1, 0);
85 ak452x_wrbit(codec, 1);
86 ak452x_wrbit(codec, 0);
88 ak452x_wrbit(codec, 1);
89 /* register address */
90 for (mask = 0x10; mask != 0; mask >>= 1)
91 ak452x_wrbit(codec, reg & mask);
93 for (mask = 0x80; mask != 0; mask >>= 1)
94 ak452x_wrbit(codec, val & mask);
98 codec->ctrl(codec->devinfo, 0, 1, 0);
100 codec->ctrl(codec->devinfo, 1, 1, 0);
103 codec->ctrl(codec->devinfo, 1, 1, 0);
110 ak452x_create(device_t dev, void *devinfo, int num, ak452x_ctrl ctrl)
112 struct ak452x_info *codec;
115 device_printf(dev, "ak452x_create(dev, devinfo, %d, ctrl)\n", num);
117 codec = (struct ak452x_info *)malloc(sizeof *codec, M_AK452X, M_NOWAIT);
121 snprintf(codec->name, AK452X_NAMELEN, "%s:ak452x%d", device_get_nameunit(dev), num);
122 codec->lock = snd_mtxcreate(codec->name, codec->name);
125 codec->devinfo = devinfo;
127 codec->type = AK452X_TYPE_4524;
129 codec->format = AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X;
130 codec->dvc = AK452X_DVC_DEMOFF | AK452X_DVC_ZTM1024 | AK452X_DVC_ZCE;
136 ak452x_destroy(struct ak452x_info *codec)
138 snd_mtxfree(codec->lock);
139 free(codec, M_AK452X);
143 ak452x_settype(struct ak452x_info *codec, unsigned int type)
145 snd_mtxlock(codec->lock);
147 snd_mtxunlock(codec->lock);
151 ak452x_setcif(struct ak452x_info *codec, unsigned int cif)
153 snd_mtxlock(codec->lock);
155 snd_mtxunlock(codec->lock);
159 ak452x_setformat(struct ak452x_info *codec, unsigned int format)
161 snd_mtxlock(codec->lock);
162 codec->format = format;
163 snd_mtxunlock(codec->lock);
167 ak452x_setdvc(struct ak452x_info *codec, unsigned int dvc)
169 snd_mtxlock(codec->lock);
171 snd_mtxunlock(codec->lock);
175 ak452x_init(struct ak452x_info *codec)
178 device_printf(codec->dev, "ak452x_init(codec)\n");
180 snd_mtxlock(codec->lock);
182 ak452x_wrcd(codec, AK4524_POWER, 0);
184 ak452x_wrcd(codec, AK4524_FORMAT, codec->format);
185 ak452x_wrcd(codec, AK4524_DVC, codec->dvc);
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);
194 ak452x_reinit(struct ak452x_info *codec)
196 snd_mtxlock(codec->lock);
198 ak452x_wrcd(codec, AK4524_RESET, 0);
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);
208 ak452x_set(struct ak452x_info *codec, int dir, unsigned int left, unsigned int right)
211 device_printf(codec->dev, "ak452x_set(codec, %d, %d, %d)\n", dir, left, right);
213 snd_mtxlock(codec->lock);
217 left = left * 127 / 100;
221 right = right * 127 / 100;
222 if (dir == PCMDIR_REC && codec->type == AK452X_TYPE_4524) {
224 device_printf(codec->dev, "ak452x_set(): AK4524(REC) %d/%d\n", left, right);
226 ak452x_wrcd(codec, AK4524_LIPGA, left);
227 ak452x_wrcd(codec, AK4524_RIPGA, right);
229 if (dir == PCMDIR_PLAY && codec->type == AK452X_TYPE_4524) {
231 device_printf(codec->dev, "ak452x_set(): AK4524(PLAY) %d/%d\n", left, right);
233 ak452x_wrcd(codec, AK4524_LOATT, left);
234 ak452x_wrcd(codec, AK4524_ROATT, right);
236 if (dir == PCMDIR_PLAY && codec->type == AK452X_TYPE_4528) {
238 device_printf(codec->dev, "ak452x_set(): AK4528(PLAY) %d/%d\n", left, right);
240 ak452x_wrcd(codec, AK4528_LOATT, left);
241 ak452x_wrcd(codec, AK4528_ROATT, right);
243 snd_mtxunlock(codec->lock);
246 MODULE_DEPEND(snd_ak452x, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
247 MODULE_VERSION(snd_ak452x, 1);