112ab72d3SAlexander Leidinger /* 212ab72d3SAlexander Leidinger * Copyright (c) 2001 Katsurajima Naoto <raven@katsurajima.seya.yokohama.jp> 312ab72d3SAlexander Leidinger * All rights reserved. 412ab72d3SAlexander Leidinger * 512ab72d3SAlexander Leidinger * Redistribution and use in source and binary forms, with or without 612ab72d3SAlexander Leidinger * modification, are permitted provided that the following conditions 712ab72d3SAlexander Leidinger * are met: 812ab72d3SAlexander Leidinger * 1. Redistributions of source code must retain the above copyright 912ab72d3SAlexander Leidinger * notice, this list of conditions and the following disclaimer. 1012ab72d3SAlexander Leidinger * 2. Redistributions in binary form must reproduce the above copyright 1112ab72d3SAlexander Leidinger * notice, this list of conditions and the following disclaimer in the 1212ab72d3SAlexander Leidinger * documentation and/or other materials provided with the distribution. 1312ab72d3SAlexander Leidinger * 1412ab72d3SAlexander Leidinger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1512ab72d3SAlexander Leidinger * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1612ab72d3SAlexander Leidinger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1712ab72d3SAlexander Leidinger * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1812ab72d3SAlexander Leidinger * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1912ab72d3SAlexander Leidinger * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2012ab72d3SAlexander Leidinger * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2112ab72d3SAlexander Leidinger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHERIN CONTRACT, STRICT 2212ab72d3SAlexander Leidinger * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2312ab72d3SAlexander Leidinger * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THEPOSSIBILITY OF 2412ab72d3SAlexander Leidinger * SUCH DAMAGE. 2512ab72d3SAlexander Leidinger * 2612ab72d3SAlexander Leidinger * $FreeBSD$ 2712ab72d3SAlexander Leidinger */ 2812ab72d3SAlexander Leidinger 2912ab72d3SAlexander Leidinger #include <dev/sound/pcm/sound.h> 3012ab72d3SAlexander Leidinger 3112ab72d3SAlexander Leidinger #include <dev/sound/pci/ak452x.h> 3212ab72d3SAlexander Leidinger 3312ab72d3SAlexander Leidinger MALLOC_DEFINE(M_AK452X, "ak452x", "ak452x codec"); 3412ab72d3SAlexander Leidinger 3512ab72d3SAlexander Leidinger #define AK452X_NAMELEN 16 3612ab72d3SAlexander Leidinger struct ak452x_info { 3712ab72d3SAlexander Leidinger device_t dev; 3812ab72d3SAlexander Leidinger ak452x_ctrl ctrl; 3912ab72d3SAlexander Leidinger void *devinfo; 4012ab72d3SAlexander Leidinger int num; /* number of this device */ 4112ab72d3SAlexander Leidinger unsigned int type; /* codec type */ 4212ab72d3SAlexander Leidinger unsigned int cif; /* Controll data Interface Format (0/1) */ 4312ab72d3SAlexander Leidinger unsigned int format; /* data format and master clock frequency */ 4412ab72d3SAlexander Leidinger unsigned int dvc; /* De-emphasis and Volume Control */ 4512ab72d3SAlexander Leidinger unsigned int left, right; 4612ab72d3SAlexander Leidinger char name[AK452X_NAMELEN]; 4712ab72d3SAlexander Leidinger void *lock; 4812ab72d3SAlexander Leidinger }; 4912ab72d3SAlexander Leidinger 5012ab72d3SAlexander Leidinger static void 5112ab72d3SAlexander Leidinger ak452x_wrbit(struct ak452x_info *codec, int bit) 5212ab72d3SAlexander Leidinger { 5312ab72d3SAlexander Leidinger unsigned int cs, cdti; 5412ab72d3SAlexander Leidinger if (codec->cif) 5512ab72d3SAlexander Leidinger cs = 1; 5612ab72d3SAlexander Leidinger else 5712ab72d3SAlexander Leidinger cs = 0; 5812ab72d3SAlexander Leidinger if (bit) 5912ab72d3SAlexander Leidinger cdti = 1; 6012ab72d3SAlexander Leidinger else 6112ab72d3SAlexander Leidinger cdti = 0; 6212ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, cs, 0, cdti); 6312ab72d3SAlexander Leidinger DELAY(1); 6412ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, cs, 1, cdti); 6512ab72d3SAlexander Leidinger DELAY(1); 6612ab72d3SAlexander Leidinger 6712ab72d3SAlexander Leidinger return; 6812ab72d3SAlexander Leidinger } 6912ab72d3SAlexander Leidinger 7012ab72d3SAlexander Leidinger static void 7112ab72d3SAlexander Leidinger ak452x_wrcd(struct ak452x_info *codec, int reg, u_int8_t val) 7212ab72d3SAlexander Leidinger { 7312ab72d3SAlexander Leidinger int mask; 7412ab72d3SAlexander Leidinger 7512ab72d3SAlexander Leidinger #if(0) 7612ab72d3SAlexander Leidinger device_printf(codec->dev, "ak452x_wrcd(codec, 0x%02x, 0x%02x)\n", reg, val); 7712ab72d3SAlexander Leidinger #endif 7812ab72d3SAlexander Leidinger /* start */ 7912ab72d3SAlexander Leidinger if (codec->cif) 8012ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, 1, 1, 0); 8112ab72d3SAlexander Leidinger else 8212ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, 0, 1, 0); 8312ab72d3SAlexander Leidinger DELAY(1); 8412ab72d3SAlexander Leidinger /* chip address */ 8512ab72d3SAlexander Leidinger ak452x_wrbit(codec, 1); 8612ab72d3SAlexander Leidinger ak452x_wrbit(codec, 0); 8712ab72d3SAlexander Leidinger /* write */ 8812ab72d3SAlexander Leidinger ak452x_wrbit(codec, 1); 8912ab72d3SAlexander Leidinger /* register address */ 9012ab72d3SAlexander Leidinger for (mask = 0x10; mask != 0; mask >>= 1) 9112ab72d3SAlexander Leidinger ak452x_wrbit(codec, reg & mask); 9212ab72d3SAlexander Leidinger /* data */ 9312ab72d3SAlexander Leidinger for (mask = 0x80; mask != 0; mask >>= 1) 9412ab72d3SAlexander Leidinger ak452x_wrbit(codec, val & mask); 9512ab72d3SAlexander Leidinger /* stop */ 9612ab72d3SAlexander Leidinger DELAY(1); 9712ab72d3SAlexander Leidinger if (codec->cif) { 9812ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, 0, 1, 0); 9912ab72d3SAlexander Leidinger DELAY(1); 10012ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, 1, 1, 0); 10112ab72d3SAlexander Leidinger } 10212ab72d3SAlexander Leidinger else { 10312ab72d3SAlexander Leidinger codec->ctrl(codec->devinfo, 1, 1, 0); 10412ab72d3SAlexander Leidinger } 10512ab72d3SAlexander Leidinger 10612ab72d3SAlexander Leidinger return; 10712ab72d3SAlexander Leidinger } 10812ab72d3SAlexander Leidinger 10912ab72d3SAlexander Leidinger struct ak452x_info * 11012ab72d3SAlexander Leidinger ak452x_create(device_t dev, void *devinfo, int num, ak452x_ctrl ctrl) 11112ab72d3SAlexander Leidinger { 11212ab72d3SAlexander Leidinger struct ak452x_info *codec; 11312ab72d3SAlexander Leidinger 11412ab72d3SAlexander Leidinger #if(0) 11512ab72d3SAlexander Leidinger device_printf(dev, "ak452x_create(dev, devinfo, %d, ctrl)\n", num); 11612ab72d3SAlexander Leidinger #endif 11712ab72d3SAlexander Leidinger codec = (struct ak452x_info *)malloc(sizeof *codec, M_AK452X, M_NOWAIT); 11812ab72d3SAlexander Leidinger if (codec == NULL) 11912ab72d3SAlexander Leidinger return NULL; 12012ab72d3SAlexander Leidinger 12112ab72d3SAlexander Leidinger snprintf(codec->name, AK452X_NAMELEN, "%s:ak452x%d", device_get_nameunit(dev), num); 122ce356b70SAlexander Leidinger codec->lock = snd_mtxcreate(codec->name, codec->name); 12312ab72d3SAlexander Leidinger codec->dev = dev; 12412ab72d3SAlexander Leidinger codec->ctrl = ctrl; 12512ab72d3SAlexander Leidinger codec->devinfo = devinfo; 12612ab72d3SAlexander Leidinger codec->num = num; 12712ab72d3SAlexander Leidinger codec->type = AK452X_TYPE_4524; 12812ab72d3SAlexander Leidinger codec->cif = 0; 12912ab72d3SAlexander Leidinger codec->format = AK452X_FORMAT_I2S | AK452X_FORMAT_256FSN | AK452X_FORMAT_1X; 13012ab72d3SAlexander Leidinger codec->dvc = AK452X_DVC_DEMOFF | AK452X_DVC_ZTM1024 | AK452X_DVC_ZCE; 13112ab72d3SAlexander Leidinger 13212ab72d3SAlexander Leidinger return codec; 13312ab72d3SAlexander Leidinger } 13412ab72d3SAlexander Leidinger 13512ab72d3SAlexander Leidinger void 13612ab72d3SAlexander Leidinger ak452x_destroy(struct ak452x_info *codec) 13712ab72d3SAlexander Leidinger { 13812ab72d3SAlexander Leidinger snd_mtxfree(codec->lock); 13912ab72d3SAlexander Leidinger free(codec, M_AK452X); 14012ab72d3SAlexander Leidinger } 14112ab72d3SAlexander Leidinger 14212ab72d3SAlexander Leidinger void 14312ab72d3SAlexander Leidinger ak452x_settype(struct ak452x_info *codec, unsigned int type) 14412ab72d3SAlexander Leidinger { 14512ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 14612ab72d3SAlexander Leidinger codec->type = type; 14712ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 14812ab72d3SAlexander Leidinger } 14912ab72d3SAlexander Leidinger 15012ab72d3SAlexander Leidinger void 15112ab72d3SAlexander Leidinger ak452x_setcif(struct ak452x_info *codec, unsigned int cif) 15212ab72d3SAlexander Leidinger { 15312ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 15412ab72d3SAlexander Leidinger codec->cif = cif; 15512ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 15612ab72d3SAlexander Leidinger } 15712ab72d3SAlexander Leidinger 15812ab72d3SAlexander Leidinger void 15912ab72d3SAlexander Leidinger ak452x_setformat(struct ak452x_info *codec, unsigned int format) 16012ab72d3SAlexander Leidinger { 16112ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 16212ab72d3SAlexander Leidinger codec->format = format; 16312ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 16412ab72d3SAlexander Leidinger } 16512ab72d3SAlexander Leidinger 16612ab72d3SAlexander Leidinger void 16712ab72d3SAlexander Leidinger ak452x_setdvc(struct ak452x_info *codec, unsigned int dvc) 16812ab72d3SAlexander Leidinger { 16912ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 170ce356b70SAlexander Leidinger codec->dvc = dvc; 17112ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 17212ab72d3SAlexander Leidinger } 17312ab72d3SAlexander Leidinger 17412ab72d3SAlexander Leidinger void 17512ab72d3SAlexander Leidinger ak452x_init(struct ak452x_info *codec) 17612ab72d3SAlexander Leidinger { 17712ab72d3SAlexander Leidinger #if(0) 17812ab72d3SAlexander Leidinger device_printf(codec->dev, "ak452x_init(codec)\n"); 17912ab72d3SAlexander Leidinger #endif 18012ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 18112ab72d3SAlexander Leidinger /* power off */ 18212ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_POWER, 0); 18312ab72d3SAlexander Leidinger /* set parameter */ 18412ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_FORMAT, codec->format); 18512ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_DVC, codec->dvc); 18612ab72d3SAlexander Leidinger /* power on */ 18712ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_POWER, AK452X_POWER_PWDA | AK452X_POWER_PWAD | AK452X_POWER_PWVR); 18812ab72d3SAlexander Leidinger /* free reset register */ 18912ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_RESET, AK452X_RESET_RSDA | AK452X_RESET_RSAD); 19012ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 19112ab72d3SAlexander Leidinger } 19212ab72d3SAlexander Leidinger 19312ab72d3SAlexander Leidinger void 19412ab72d3SAlexander Leidinger ak452x_reinit(struct ak452x_info *codec) 19512ab72d3SAlexander Leidinger { 19612ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 19712ab72d3SAlexander Leidinger /* reset */ 19812ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_RESET, 0); 19912ab72d3SAlexander Leidinger /* set parameter */ 20012ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_FORMAT, codec->format); 20112ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_DVC, codec->dvc); 20212ab72d3SAlexander Leidinger /* free reset register */ 20312ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_RESET, AK452X_RESET_RSDA | AK452X_RESET_RSAD); 20412ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 20512ab72d3SAlexander Leidinger } 20612ab72d3SAlexander Leidinger 20712ab72d3SAlexander Leidinger void 20812ab72d3SAlexander Leidinger ak452x_set(struct ak452x_info *codec, int dir, unsigned int left, unsigned int right) 20912ab72d3SAlexander Leidinger { 21012ab72d3SAlexander Leidinger #if(0) 21112ab72d3SAlexander Leidinger device_printf(codec->dev, "ak452x_set(codec, %d, %d, %d)\n", dir, left, right); 21212ab72d3SAlexander Leidinger #endif 21312ab72d3SAlexander Leidinger snd_mtxlock(codec->lock); 21412ab72d3SAlexander Leidinger if (left >= 100) 21512ab72d3SAlexander Leidinger left = 127; 21612ab72d3SAlexander Leidinger else 21712ab72d3SAlexander Leidinger left = left * 127 / 100; 21812ab72d3SAlexander Leidinger if (right >= 100) 21912ab72d3SAlexander Leidinger right = 127; 22012ab72d3SAlexander Leidinger else 22112ab72d3SAlexander Leidinger right = right * 127 / 100; 22212ab72d3SAlexander Leidinger if (dir == PCMDIR_REC && codec->type == AK452X_TYPE_4524) { 22312ab72d3SAlexander Leidinger #if(0) 22412ab72d3SAlexander Leidinger device_printf(codec->dev, "ak452x_set(): AK4524(REC) %d/%d\n", left, right); 22512ab72d3SAlexander Leidinger #endif 22612ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_LIPGA, left); 22712ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_RIPGA, right); 22812ab72d3SAlexander Leidinger } 22912ab72d3SAlexander Leidinger if (dir == PCMDIR_PLAY && codec->type == AK452X_TYPE_4524) { 23012ab72d3SAlexander Leidinger #if(0) 23112ab72d3SAlexander Leidinger device_printf(codec->dev, "ak452x_set(): AK4524(PLAY) %d/%d\n", left, right); 23212ab72d3SAlexander Leidinger #endif 23312ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_LOATT, left); 23412ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4524_ROATT, right); 23512ab72d3SAlexander Leidinger } 23612ab72d3SAlexander Leidinger if (dir == PCMDIR_PLAY && codec->type == AK452X_TYPE_4528) { 23712ab72d3SAlexander Leidinger #if(0) 23812ab72d3SAlexander Leidinger device_printf(codec->dev, "ak452x_set(): AK4528(PLAY) %d/%d\n", left, right); 23912ab72d3SAlexander Leidinger #endif 24012ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4528_LOATT, left); 24112ab72d3SAlexander Leidinger ak452x_wrcd(codec, AK4528_ROATT, right); 24212ab72d3SAlexander Leidinger } 24312ab72d3SAlexander Leidinger snd_mtxunlock(codec->lock); 24412ab72d3SAlexander Leidinger } 24512ab72d3SAlexander Leidinger 246ce356b70SAlexander Leidinger MODULE_DEPEND(snd_ak452x, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER); 24712ab72d3SAlexander Leidinger MODULE_VERSION(snd_ak452x, 1); 248