xref: /freebsd/sys/dev/sound/pci/spicds.c (revision 95ee2897)
1b40d3421SJoel Dahl /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4f198ead2SAlexander Leidinger  * Copyright (c) 2006 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
512ab72d3SAlexander Leidinger  * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp>
612ab72d3SAlexander Leidinger  * All rights reserved.
712ab72d3SAlexander Leidinger  *
812ab72d3SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
912ab72d3SAlexander Leidinger  * modification, are permitted provided that the following conditions
1012ab72d3SAlexander Leidinger  * are met:
1112ab72d3SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
1212ab72d3SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer.
1312ab72d3SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
1412ab72d3SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
1512ab72d3SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
1612ab72d3SAlexander Leidinger  *
1712ab72d3SAlexander Leidinger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1812ab72d3SAlexander Leidinger  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1912ab72d3SAlexander Leidinger  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2012ab72d3SAlexander Leidinger  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2112ab72d3SAlexander Leidinger  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2212ab72d3SAlexander Leidinger  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2312ab72d3SAlexander Leidinger  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2412ab72d3SAlexander Leidinger  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT
2512ab72d3SAlexander Leidinger  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2612ab72d3SAlexander Leidinger  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF
2712ab72d3SAlexander Leidinger  * SUCH DAMAGE.
2812ab72d3SAlexander Leidinger  */
2912ab72d3SAlexander Leidinger 
3090da2b28SAriff Abdullah #ifdef HAVE_KERNEL_OPTION_HEADERS
3190da2b28SAriff Abdullah #include "opt_snd.h"
3290da2b28SAriff Abdullah #endif
3390da2b28SAriff Abdullah 
3412ab72d3SAlexander Leidinger #include <dev/sound/pcm/sound.h>
3512ab72d3SAlexander Leidinger 
36f198ead2SAlexander Leidinger #include <dev/sound/pci/spicds.h>
3712ab72d3SAlexander Leidinger 
38d745c852SEd Schouten static MALLOC_DEFINE(M_SPICDS, "spicds", "SPI codec");
3912ab72d3SAlexander Leidinger 
40f198ead2SAlexander Leidinger #define SPICDS_NAMELEN	16
41f198ead2SAlexander Leidinger struct spicds_info {
4212ab72d3SAlexander Leidinger 	device_t dev;
43f198ead2SAlexander Leidinger 	spicds_ctrl ctrl;
4412ab72d3SAlexander Leidinger 	void *devinfo;
4512ab72d3SAlexander Leidinger 	int num; /* number of this device */
4612ab72d3SAlexander Leidinger 	unsigned int type;   /* codec type */
4712ab72d3SAlexander Leidinger 	unsigned int cif;    /* Controll data Interface Format (0/1) */
4812ab72d3SAlexander Leidinger 	unsigned int format; /* data format and master clock frequency */
4912ab72d3SAlexander Leidinger 	unsigned int dvc;    /* De-emphasis and Volume Control */
5012ab72d3SAlexander Leidinger 	unsigned int left, right;
51f198ead2SAlexander Leidinger 	char name[SPICDS_NAMELEN];
52d82080b4SAriff Abdullah 	struct mtx *lock;
5312ab72d3SAlexander Leidinger };
5412ab72d3SAlexander Leidinger 
5512ab72d3SAlexander Leidinger static void
spicds_wrbit(struct spicds_info * codec,int bit)56f198ead2SAlexander Leidinger spicds_wrbit(struct spicds_info *codec, int bit)
5712ab72d3SAlexander Leidinger {
5812ab72d3SAlexander Leidinger 	unsigned int cs, cdti;
5912ab72d3SAlexander Leidinger 	if (codec->cif)
6012ab72d3SAlexander Leidinger 		cs = 1;
6112ab72d3SAlexander Leidinger 	else
6212ab72d3SAlexander Leidinger 		cs = 0;
6312ab72d3SAlexander Leidinger 	if (bit)
6412ab72d3SAlexander Leidinger 		cdti = 1;
6512ab72d3SAlexander Leidinger 	else
6612ab72d3SAlexander Leidinger 		cdti = 0;
6712ab72d3SAlexander Leidinger 	codec->ctrl(codec->devinfo, cs, 0, cdti);
6812ab72d3SAlexander Leidinger 	DELAY(1);
6912ab72d3SAlexander Leidinger 	codec->ctrl(codec->devinfo, cs, 1, cdti);
7012ab72d3SAlexander Leidinger 	DELAY(1);
7112ab72d3SAlexander Leidinger 
7212ab72d3SAlexander Leidinger 	return;
7312ab72d3SAlexander Leidinger }
7412ab72d3SAlexander Leidinger 
7512ab72d3SAlexander Leidinger static void
spicds_wrcd(struct spicds_info * codec,int reg,u_int16_t val)76f198ead2SAlexander Leidinger spicds_wrcd(struct spicds_info *codec, int reg, u_int16_t val)
7712ab72d3SAlexander Leidinger {
7812ab72d3SAlexander Leidinger 	int mask;
7912ab72d3SAlexander Leidinger 
8012ab72d3SAlexander Leidinger #if(0)
81f198ead2SAlexander Leidinger 	device_printf(codec->dev, "spicds_wrcd(codec, 0x%02x, 0x%02x)\n", reg, val);
8212ab72d3SAlexander Leidinger #endif
8312ab72d3SAlexander Leidinger 	/* start */
8412ab72d3SAlexander Leidinger 	if (codec->cif)
8512ab72d3SAlexander Leidinger 		codec->ctrl(codec->devinfo, 1, 1, 0);
8612ab72d3SAlexander Leidinger 	else
8712ab72d3SAlexander Leidinger 		codec->ctrl(codec->devinfo, 0, 1, 0);
8812ab72d3SAlexander Leidinger 	DELAY(1);
89f198ead2SAlexander Leidinger 	if (codec->type != SPICDS_TYPE_WM8770) {
90f198ead2SAlexander Leidinger 	if (codec->type == SPICDS_TYPE_AK4381) {
91f198ead2SAlexander Leidinger 	/* AK4381 chip address */
92f198ead2SAlexander Leidinger         spicds_wrbit(codec, 0);
93f198ead2SAlexander Leidinger         spicds_wrbit(codec, 1);
94f198ead2SAlexander Leidinger 	}
95ccb43d8dSJoel Dahl 	else if (codec->type == SPICDS_TYPE_AK4396)
96ccb43d8dSJoel Dahl 	{
97ccb43d8dSJoel Dahl 	/* AK4396 chip address */
98ccb43d8dSJoel Dahl         spicds_wrbit(codec, 0);
99ccb43d8dSJoel Dahl         spicds_wrbit(codec, 0);
100ccb43d8dSJoel Dahl 	}
101f198ead2SAlexander Leidinger 	else {
10212ab72d3SAlexander Leidinger 	/* chip address */
103f198ead2SAlexander Leidinger 	spicds_wrbit(codec, 1);
104f198ead2SAlexander Leidinger 	spicds_wrbit(codec, 0);
105f198ead2SAlexander Leidinger 	}
10612ab72d3SAlexander Leidinger 	/* write */
107f198ead2SAlexander Leidinger 	spicds_wrbit(codec, 1);
10812ab72d3SAlexander Leidinger 	/* register address */
10912ab72d3SAlexander Leidinger 	for (mask = 0x10; mask != 0; mask >>= 1)
110f198ead2SAlexander Leidinger 		spicds_wrbit(codec, reg & mask);
11112ab72d3SAlexander Leidinger 	/* data */
11212ab72d3SAlexander Leidinger 	for (mask = 0x80; mask != 0; mask >>= 1)
113f198ead2SAlexander Leidinger 		spicds_wrbit(codec, val & mask);
11412ab72d3SAlexander Leidinger 	/* stop */
11512ab72d3SAlexander Leidinger 	DELAY(1);
116f198ead2SAlexander Leidinger 	}
117f198ead2SAlexander Leidinger 	else {
118f198ead2SAlexander Leidinger         /* register address */
119f198ead2SAlexander Leidinger         for (mask = 0x40; mask != 0; mask >>= 1)
120f198ead2SAlexander Leidinger                 spicds_wrbit(codec, reg & mask);
121f198ead2SAlexander Leidinger         /* data */
122f198ead2SAlexander Leidinger         for (mask = 0x100; mask != 0; mask >>= 1)
123f198ead2SAlexander Leidinger                 spicds_wrbit(codec, val & mask);
124f198ead2SAlexander Leidinger         /* stop */
125f198ead2SAlexander Leidinger         DELAY(1);
126f198ead2SAlexander Leidinger 	}
12712ab72d3SAlexander Leidinger 	if (codec->cif) {
12812ab72d3SAlexander Leidinger 		codec->ctrl(codec->devinfo, 0, 1, 0);
12912ab72d3SAlexander Leidinger 		DELAY(1);
13012ab72d3SAlexander Leidinger 		codec->ctrl(codec->devinfo, 1, 1, 0);
13112ab72d3SAlexander Leidinger 	}
13212ab72d3SAlexander Leidinger 	else {
13312ab72d3SAlexander Leidinger 		codec->ctrl(codec->devinfo, 1, 1, 0);
13412ab72d3SAlexander Leidinger 	}
13512ab72d3SAlexander Leidinger 
13612ab72d3SAlexander Leidinger 	return;
13712ab72d3SAlexander Leidinger }
13812ab72d3SAlexander Leidinger 
139f198ead2SAlexander Leidinger struct spicds_info *
spicds_create(device_t dev,void * devinfo,int num,spicds_ctrl ctrl)140f198ead2SAlexander Leidinger spicds_create(device_t dev, void *devinfo, int num, spicds_ctrl ctrl)
14112ab72d3SAlexander Leidinger {
142f198ead2SAlexander Leidinger 	struct spicds_info *codec;
14312ab72d3SAlexander Leidinger 
14412ab72d3SAlexander Leidinger #if(0)
145f198ead2SAlexander Leidinger 	device_printf(dev, "spicds_create(dev, devinfo, %d, ctrl)\n", num);
14612ab72d3SAlexander Leidinger #endif
147f198ead2SAlexander Leidinger 	codec = (struct spicds_info *)malloc(sizeof *codec, M_SPICDS, M_NOWAIT);
14812ab72d3SAlexander Leidinger 	if (codec == NULL)
14912ab72d3SAlexander Leidinger 		return NULL;
15012ab72d3SAlexander Leidinger 
151f198ead2SAlexander Leidinger 	snprintf(codec->name, SPICDS_NAMELEN, "%s:spicds%d", device_get_nameunit(dev), num);
152ce356b70SAlexander Leidinger 	codec->lock = snd_mtxcreate(codec->name, codec->name);
15312ab72d3SAlexander Leidinger 	codec->dev = dev;
15412ab72d3SAlexander Leidinger 	codec->ctrl = ctrl;
15512ab72d3SAlexander Leidinger 	codec->devinfo = devinfo;
15612ab72d3SAlexander Leidinger 	codec->num = num;
157f198ead2SAlexander Leidinger 	codec->type = SPICDS_TYPE_AK4524;
15812ab72d3SAlexander Leidinger 	codec->cif = 0;
15912ab72d3SAlexander Leidinger 	codec->format = AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X;
16012ab72d3SAlexander Leidinger 	codec->dvc = AK452X_DVC_DEMOFF | AK452X_DVC_ZTM1024 | AK452X_DVC_ZCE;
16112ab72d3SAlexander Leidinger 
16212ab72d3SAlexander Leidinger 	return codec;
16312ab72d3SAlexander Leidinger }
16412ab72d3SAlexander Leidinger 
16512ab72d3SAlexander Leidinger void
spicds_destroy(struct spicds_info * codec)166f198ead2SAlexander Leidinger spicds_destroy(struct spicds_info *codec)
16712ab72d3SAlexander Leidinger {
16812ab72d3SAlexander Leidinger 	snd_mtxfree(codec->lock);
169f198ead2SAlexander Leidinger 	free(codec, M_SPICDS);
17012ab72d3SAlexander Leidinger }
17112ab72d3SAlexander Leidinger 
17212ab72d3SAlexander Leidinger void
spicds_settype(struct spicds_info * codec,unsigned int type)173f198ead2SAlexander Leidinger spicds_settype(struct spicds_info *codec, unsigned int type)
17412ab72d3SAlexander Leidinger {
17512ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
17612ab72d3SAlexander Leidinger 	codec->type = type;
17712ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
17812ab72d3SAlexander Leidinger }
17912ab72d3SAlexander Leidinger 
18012ab72d3SAlexander Leidinger void
spicds_setcif(struct spicds_info * codec,unsigned int cif)181f198ead2SAlexander Leidinger spicds_setcif(struct spicds_info *codec, unsigned int cif)
18212ab72d3SAlexander Leidinger {
18312ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
18412ab72d3SAlexander Leidinger 	codec->cif = cif;
18512ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
18612ab72d3SAlexander Leidinger }
18712ab72d3SAlexander Leidinger 
18812ab72d3SAlexander Leidinger void
spicds_setformat(struct spicds_info * codec,unsigned int format)189f198ead2SAlexander Leidinger spicds_setformat(struct spicds_info *codec, unsigned int format)
19012ab72d3SAlexander Leidinger {
19112ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
19212ab72d3SAlexander Leidinger 	codec->format = format;
19312ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
19412ab72d3SAlexander Leidinger }
19512ab72d3SAlexander Leidinger 
19612ab72d3SAlexander Leidinger void
spicds_setdvc(struct spicds_info * codec,unsigned int dvc)197f198ead2SAlexander Leidinger spicds_setdvc(struct spicds_info *codec, unsigned int dvc)
19812ab72d3SAlexander Leidinger {
19912ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
200ce356b70SAlexander Leidinger 	codec->dvc = dvc;
20112ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
20212ab72d3SAlexander Leidinger }
20312ab72d3SAlexander Leidinger 
20412ab72d3SAlexander Leidinger void
spicds_init(struct spicds_info * codec)205f198ead2SAlexander Leidinger spicds_init(struct spicds_info *codec)
20612ab72d3SAlexander Leidinger {
20712ab72d3SAlexander Leidinger #if(0)
208f198ead2SAlexander Leidinger 	device_printf(codec->dev, "spicds_init(codec)\n");
20912ab72d3SAlexander Leidinger #endif
21012ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
211f198ead2SAlexander Leidinger 	if (codec->type == SPICDS_TYPE_AK4524 ||\
212f198ead2SAlexander Leidinger 	    codec->type == SPICDS_TYPE_AK4528) {
21312ab72d3SAlexander Leidinger 		/* power off */
214f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_POWER, 0);
21512ab72d3SAlexander Leidinger 		/* set parameter */
216f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_FORMAT, codec->format);
217f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_DVC, codec->dvc);
21812ab72d3SAlexander Leidinger 		/* power on */
219f6695864SBaptiste Daroussin 		spicds_wrcd(codec, AK4524_POWER,
220f6695864SBaptiste Daroussin 		    AK452X_POWER_PWDA | AK452X_POWER_PWAD | AK452X_POWER_PWVR);
22112ab72d3SAlexander Leidinger 		/* free reset register */
222f6695864SBaptiste Daroussin 		spicds_wrcd(codec, AK4524_RESET,
223f6695864SBaptiste Daroussin 		    AK452X_RESET_RSDA | AK452X_RESET_RSAD);
224f198ead2SAlexander Leidinger 	}
225f198ead2SAlexander Leidinger 	if (codec->type == SPICDS_TYPE_WM8770) {
226f198ead2SAlexander Leidinger 		/* WM8770 init values are taken from ALSA */
227f6695864SBaptiste Daroussin 
228f198ead2SAlexander Leidinger 		/* These come first to reduce init pop noise */
229f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x1b, 0x044);	/* ADC Mux (AC'97 source) */
230f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x1c, 0x00B);	/* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
231f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x1d, 0x009);	/* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
232f198ead2SAlexander Leidinger 
233f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x18, 0x000);	/* All power-up */
234f198ead2SAlexander Leidinger 
235f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x16, 0x122);	/* I2S, normal polarity, 24bit */
236f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x17, 0x022);	/* 256fs, slave mode */
237f198ead2SAlexander Leidinger 
238f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x19, 0x000);	/* -12dB ADC/L */
239f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x1a, 0x000);	/* -12dB ADC/R */
240f198ead2SAlexander Leidinger 	}
241f198ead2SAlexander Leidinger 	if (codec->type == SPICDS_TYPE_AK4358)
242f198ead2SAlexander Leidinger 		spicds_wrcd(codec, 0x00, 0x07);		/* I2S, 24bit, power-up */
243f198ead2SAlexander Leidinger 	if (codec->type == SPICDS_TYPE_AK4381)
2443141a8dcSAlexander Leidinger 		spicds_wrcd(codec, 0x00, 0x8f);		/* I2S, 24bit, power-up */
245ccb43d8dSJoel Dahl 	if (codec->type == SPICDS_TYPE_AK4396)
246ccb43d8dSJoel Dahl 		spicds_wrcd(codec, 0x00, 0x07);		/* I2S, 24bit, power-up */
24712ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
24812ab72d3SAlexander Leidinger }
24912ab72d3SAlexander Leidinger 
25012ab72d3SAlexander Leidinger void
spicds_reinit(struct spicds_info * codec)251f198ead2SAlexander Leidinger spicds_reinit(struct spicds_info *codec)
25212ab72d3SAlexander Leidinger {
25312ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
254f198ead2SAlexander Leidinger 	if (codec->type != SPICDS_TYPE_WM8770) {
25512ab72d3SAlexander Leidinger 		/* reset */
256f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_RESET, 0);
25712ab72d3SAlexander Leidinger 		/* set parameter */
258f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_FORMAT, codec->format);
259f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_DVC, codec->dvc);
26012ab72d3SAlexander Leidinger 		/* free reset register */
261f6695864SBaptiste Daroussin 		spicds_wrcd(codec, AK4524_RESET,
262f6695864SBaptiste Daroussin 		    AK452X_RESET_RSDA | AK452X_RESET_RSAD);
263f6695864SBaptiste Daroussin 	} else {
264f198ead2SAlexander Leidinger 		/* WM8770 reinit */
265f198ead2SAlexander Leidinger 		/* AK4358 reinit */
266f198ead2SAlexander Leidinger 		/* AK4381 reinit */
267f198ead2SAlexander Leidinger 	}
26812ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
26912ab72d3SAlexander Leidinger }
27012ab72d3SAlexander Leidinger 
27112ab72d3SAlexander Leidinger void
spicds_set(struct spicds_info * codec,int dir,unsigned int left,unsigned int right)272f198ead2SAlexander Leidinger spicds_set(struct spicds_info *codec, int dir, unsigned int left, unsigned int right)
27312ab72d3SAlexander Leidinger {
27412ab72d3SAlexander Leidinger #if(0)
275f198ead2SAlexander Leidinger 	device_printf(codec->dev, "spicds_set(codec, %d, %d, %d)\n", dir, left, right);
27612ab72d3SAlexander Leidinger #endif
27712ab72d3SAlexander Leidinger 	snd_mtxlock(codec->lock);
27812ab72d3SAlexander Leidinger 	if (left >= 100)
279ccb43d8dSJoel Dahl 		if ((codec->type == SPICDS_TYPE_AK4381) || \
280ccb43d8dSJoel Dahl 		(codec->type == SPICDS_TYPE_AK4396))
281f198ead2SAlexander Leidinger 			left = 255;
282f198ead2SAlexander Leidinger 		else
28312ab72d3SAlexander Leidinger 			left = 127;
28412ab72d3SAlexander Leidinger 	else
285f198ead2SAlexander Leidinger 		switch (codec->type) {
286f198ead2SAlexander Leidinger 		case SPICDS_TYPE_WM8770:
287f198ead2SAlexander Leidinger 			left = left + 27;
288f198ead2SAlexander Leidinger 			break;
289577fedb6SRui Paulo 		case SPICDS_TYPE_AK4381:
290577fedb6SRui Paulo 		case SPICDS_TYPE_AK4396:
291f198ead2SAlexander Leidinger 			left = left * 255 / 100;
292f198ead2SAlexander Leidinger 			break;
293f198ead2SAlexander Leidinger 		default:
29412ab72d3SAlexander Leidinger 			left = left * 127 / 100;
295f198ead2SAlexander Leidinger 		}
29612ab72d3SAlexander Leidinger 	if (right >= 100)
297ccb43d8dSJoel Dahl 		if ((codec->type == SPICDS_TYPE_AK4381) || \
298ccb43d8dSJoel Dahl 		(codec->type == SPICDS_TYPE_AK4396))
299f198ead2SAlexander Leidinger                         right = 255;
300f198ead2SAlexander Leidinger                 else
30112ab72d3SAlexander Leidinger 			right  = 127;
30212ab72d3SAlexander Leidinger 	else
303f198ead2SAlexander Leidinger 		switch (codec->type) {
304f198ead2SAlexander Leidinger 		case SPICDS_TYPE_WM8770:
305f198ead2SAlexander Leidinger                         right = right + 27;
306f198ead2SAlexander Leidinger 			break;
3073141a8dcSAlexander Leidinger 		case SPICDS_TYPE_AK4381:
3083141a8dcSAlexander Leidinger 		case SPICDS_TYPE_AK4396:
309f198ead2SAlexander Leidinger 			right = right * 255 / 100;
310f198ead2SAlexander Leidinger 			break;
311f198ead2SAlexander Leidinger                 default:
31212ab72d3SAlexander Leidinger                         right = right * 127 / 100;
31312ab72d3SAlexander Leidinger 		}
314f198ead2SAlexander Leidinger 	if (dir == PCMDIR_REC && codec->type == SPICDS_TYPE_AK4524) {
31512ab72d3SAlexander Leidinger #if(0)
316f198ead2SAlexander Leidinger 		device_printf(codec->dev, "spicds_set(): AK4524(REC) %d/%d\n", left, right);
31712ab72d3SAlexander Leidinger #endif
318f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_LIPGA, left);
319f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_RIPGA, right);
32012ab72d3SAlexander Leidinger 	}
321f198ead2SAlexander Leidinger 	if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4524) {
32212ab72d3SAlexander Leidinger #if(0)
323f198ead2SAlexander Leidinger 		device_printf(codec->dev, "spicds_set(): AK4524(PLAY) %d/%d\n", left, right);
32412ab72d3SAlexander Leidinger #endif
325f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_LOATT, left);
326f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4524_ROATT, right);
32712ab72d3SAlexander Leidinger 	}
328f198ead2SAlexander Leidinger 	if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4528) {
329f198ead2SAlexander Leidinger #if(0)
330f198ead2SAlexander Leidinger 		device_printf(codec->dev, "spicds_set(): AK4528(PLAY) %d/%d\n", left, right);
331f198ead2SAlexander Leidinger #endif
332f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4528_LOATT, left);
333f198ead2SAlexander Leidinger 		spicds_wrcd(codec, AK4528_ROATT, right);
334f198ead2SAlexander Leidinger 	}
335f198ead2SAlexander Leidinger         if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_WM8770) {
336f198ead2SAlexander Leidinger #if(0)
337f198ead2SAlexander Leidinger                 device_printf(codec->dev, "spicds_set(): WM8770(PLAY) %d/%d\n", left, right);
338f198ead2SAlexander Leidinger #endif
339f198ead2SAlexander Leidinger                 spicds_wrcd(codec, WM8770_AOATT_L1, left | WM8770_AOATT_UPDATE);
340f198ead2SAlexander Leidinger                 spicds_wrcd(codec, WM8770_AOATT_R1, right | WM8770_AOATT_UPDATE);
341f198ead2SAlexander Leidinger         }
342f198ead2SAlexander Leidinger         if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4358) {
343f198ead2SAlexander Leidinger #if(0)
344f198ead2SAlexander Leidinger                 device_printf(codec->dev, "spicds_set(): AK4358(PLAY) %d/%d\n", left, right);
345f198ead2SAlexander Leidinger #endif
346f198ead2SAlexander Leidinger                 spicds_wrcd(codec, AK4358_LO1ATT, left | AK4358_OATT_ENABLE);
347f198ead2SAlexander Leidinger                 spicds_wrcd(codec, AK4358_RO1ATT, right | AK4358_OATT_ENABLE);
348f198ead2SAlexander Leidinger         }
349f198ead2SAlexander Leidinger         if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4381) {
350f198ead2SAlexander Leidinger #if(0)
351f198ead2SAlexander Leidinger                 device_printf(codec->dev, "spicds_set(): AK4381(PLAY) %d/%d\n", left, right);
352f198ead2SAlexander Leidinger #endif
353f198ead2SAlexander Leidinger                 spicds_wrcd(codec, AK4381_LOATT, left);
354f198ead2SAlexander Leidinger                 spicds_wrcd(codec, AK4381_ROATT, right);
355f198ead2SAlexander Leidinger         }
356f198ead2SAlexander Leidinger 
357ccb43d8dSJoel Dahl         if (dir == PCMDIR_PLAY && codec->type == SPICDS_TYPE_AK4396) {
358ccb43d8dSJoel Dahl #if(0)
359ccb43d8dSJoel Dahl                 device_printf(codec->dev, "spicds_set(): AK4396(PLAY) %d/%d\n", left, right);
360ccb43d8dSJoel Dahl #endif
361ccb43d8dSJoel Dahl                 spicds_wrcd(codec, AK4396_LOATT, left);
362ccb43d8dSJoel Dahl                 spicds_wrcd(codec, AK4396_ROATT, right);
363ccb43d8dSJoel Dahl         }
364ccb43d8dSJoel Dahl 
36512ab72d3SAlexander Leidinger 	snd_mtxunlock(codec->lock);
36612ab72d3SAlexander Leidinger }
36712ab72d3SAlexander Leidinger 
368f198ead2SAlexander Leidinger MODULE_DEPEND(snd_spicds, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
369f198ead2SAlexander Leidinger MODULE_VERSION(snd_spicds, 1);
370