88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER START
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The contents of this file are subject to the terms of the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Common Development and Distribution License (the "License").
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You may not use this file except in compliance with the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * or http://www.opensolaris.org/os/licensing.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * See the License for the specific language governing permissions
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and limitations under the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER END
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Use is subject to license terms.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Purpose: Creative/Ensoniq AudioPCI driver (ES1370)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This driver is used with the original Ensoniq AudioPCI.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This file is part of Open Sound System
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Copyright (C) 4Front Technologies 1996-2008.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This software is released under CDDL 1.0 source license.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * See the COPYING file included in the main directory of this source
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * distribution for the license terms and conditions.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/audio/audio_driver.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/note.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/pci.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include "audiopci.h"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The original OSS driver used a single duplex engine and a separate
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * playback only engine. Instead, we expose three engines, one for input
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and two for output.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define ENSONIQ_VENDOR_ID 0x1274
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define CREATIVE_VENDOR_ID 0x1102
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define ENSONIQ_ES1370 0x5000
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define DRVNAME "audiopci"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_MIC 0
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_LINEIN 1
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_CD 2
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_VIDEO 3
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_PHONE 4
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INSRCS 0x1f /* bits 0-4 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic const char *audiopci_insrcs[] = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_MIC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_LINEIN,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_CD,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_VIDEO,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_PHONE,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoretypedef struct audiopci_port
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Audio parameters */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int speed;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int fmt;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int num;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PORT_DAC 0
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PORT_SYN 1
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PORT_ADC 2
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PORT_MAX PORT_ADC
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caddr_t kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t paddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t acch;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_handle_t dmah;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned nframes;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned frameno;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t count;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore struct audiopci_dev *dev;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_engine_t *engine;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore} audiopci_port_t;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoretypedef enum {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_VOLUME = 0,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_FRONT,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_MONO,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_MIC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_LINE,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_CD,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_VID,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_PHONE,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_MICBOOST,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_RECSRC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_MONSRC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CTL_NUM /* must be last */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore} audiopci_ctrl_num_t;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoretypedef struct audiopci_ctrl
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore struct audiopci_dev *dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_ctrl_t *ctrl;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_num_t num;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore} audiopci_ctrl_t;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoretypedef struct audiopci_dev
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmutex_t mutex;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t devid;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t ak_regs[0x20];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int micbias;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Controls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t controls[CTL_NUM];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#if 0
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *micbias;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t port[PORT_MAX + 1];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caddr_t regs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t acch;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore} audiopci_dev_t;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic ddi_device_acc_attr_t acc_attr = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DEVICE_ATTR_V0,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_STRUCTURE_LE_ACC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_STRICTORDER_ACC
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic ddi_device_acc_attr_t buf_attr = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DEVICE_ATTR_V0,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_NEVERSWAP_ACC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_STRICTORDER_ACC
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The hardware appears to be able to address up to 16-bits worth of longwords,
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * giving a total address space of 256K. But we need substantially less.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore#define AUDIOPCI_BUF_LEN (16384)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic ddi_dma_attr_t dma_attr = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DMA_ATTR_VERSION, /* dma_attr_version */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0, /* dma_attr_addr_lo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0xffffffffU, /* dma_attr_addr_hi */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3ffff, /* dma_attr_count_max */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x8, /* dma_attr_align */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x7f, /* dma_attr_burstsizes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1, /* dma_attr_minxfer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3ffff, /* dma_attr_maxxfer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3ffff, /* dma_attr_seg */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1, /* dma_attr_sgllen */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1, /* dma_attr_granular */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0 /* dma_attr_flags */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define GET8(dev, offset) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define GET16(dev, offset) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define GET32(dev, offset) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PUT8(dev, offset, v) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PUT16(dev, offset, v) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PUT32(dev, offset, v) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define CLR8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) & ~(v))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define SET8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) | (v))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define CLR16(dev, offset, v) PUT16(dev, offset, GET16(dev, offset) & ~(v))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define SET16(dev, offset, v) PUT16(dev, offset, GET16(dev, offset) | (v))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiopci_init_hw(audiopci_dev_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiopci_init_port(audiopci_port_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint16_t audiopci_dac_rate(int);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiopci_add_controls(audiopci_dev_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiopci_del_controls(audiopci_dev_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiopci_ak_write(audiopci_dev_t *, uint16_t, uint8_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_ak_wait(audiopci_dev_t *dev, uint8_t wstat)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 4000; i; i--) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!(GET8(dev, CONC_bCODECSTAT_OFF) & wstat))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_ak_idle(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < 5; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audiopci_ak_wait(dev, CONC_CSTAT_CSTAT) == DDI_SUCCESS)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev, "timed out waiting for codec to idle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_ak_write(audiopci_dev_t *dev, uint16_t addr, uint8_t data)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t wstat;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* shadow the value */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev->ak_regs[addr] = data;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore wstat = addr == CODEC_RESET_PWRD ? CONC_CSTAT_CWRIP : CONC_CSTAT_CSTAT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* wait for codec to be available */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audiopci_ak_wait(dev, wstat) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev, "timeout waiting for codec");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(dev, CONC_wCODECCTL_OFF, (addr << 8) | data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_writemem(audiopci_dev_t *dev, uint32_t page, uint32_t offs,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t data)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Select memory page */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(dev, CONC_bMEMPAGE_OFF, page);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(dev, offs, data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint32_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_readmem(audiopci_dev_t *dev, uint32_t page, uint32_t offs)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(dev, CONC_bMEMPAGE_OFF, page); /* Select memory page */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (GET32(dev, offs));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Audio routines
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_format(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (AUDIO_FORMAT_S16_LE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_channels(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (2);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_rate(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (port->speed);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_init_port(audiopci_port_t *port)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = port->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (port->num) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_DAC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set physical address of the DMA buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_writemem(dev, CONC_DACCTL_PAGE, CONC_dDACPADDR_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set DAC rate */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(dev, CONC_wDACRATE_OFF, audiopci_dac_rate(48000));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set format */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bSERFMT_OFF);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_PCM_DAC_16BIT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_PCM_DAC_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSKIPC_OFF, 0x10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERFMT_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set the frame count */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_writemem(dev, CONC_DACCTL_PAGE, CONC_wDACFC_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->nframes - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set # of frames between interrupts */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore PUT16(dev, CONC_wDACIC_OFF, port->nframes - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_SYN:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set physical address of the DMA buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_writemem(dev, CONC_SYNCTL_PAGE, CONC_dSYNPADDR_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set rate - we force to 44.1 kHz */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_SYN_44KHZ);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set format */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bSERFMT_OFF);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_PCM_SYN_16BIT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_PCM_SYN_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERFMT_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set the frame count */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_writemem(dev, CONC_SYNCTL_PAGE, CONC_wSYNFC_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->nframes - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set # of frames between interrupts */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore PUT16(dev, CONC_wSYNIC_OFF, port->nframes - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_ADC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set physical address of the DMA buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_writemem(dev, CONC_ADCCTL_PAGE, CONC_dADCPADDR_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set ADC rate */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(dev, CONC_wDACRATE_OFF, audiopci_dac_rate(48000));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set format - for input we only support 16 bit input */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bSERFMT_OFF);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_PCM_ADC_16BIT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_PCM_ADC_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSKIPC_OFF, 0x10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERFMT_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set the frame count */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_writemem(dev, CONC_ADCCTL_PAGE, CONC_wADCFC_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->nframes - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Set # of frames between interrupts */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore PUT16(dev, CONC_wADCIC_OFF, port->nframes - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->frameno = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amoreaudiopci_open(void *arg, int flag, unsigned *nframes, caddr_t *bufp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(flag));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* NB: frame size = 4 (16-bit stereo) */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore port->nframes = AUDIOPCI_BUF_LEN / 4;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->count = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore *nframes = port->nframes;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *bufp = port->kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_start(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = port->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audiopci_init_port(port);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore switch (port->num) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore case PORT_DAC:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_DAC_EN);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore break;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore case PORT_SYN:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_SYN_EN);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore break;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore case PORT_ADC:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore SET8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_stop(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = port->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore switch (port->num) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore case PORT_DAC:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_DAC_EN);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore break;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore case PORT_SYN:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_SYN_EN);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore break;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore case PORT_ADC:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CLR8(dev, CONC_bDEVCTL_OFF, CONC_DEVCTL_ADC_EN);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic uint64_t
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amoreaudiopci_count(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audiopci_port_t *port = arg;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audiopci_dev_t *dev = port->dev;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint64_t val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t page, offs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int frameno, n;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (port->num) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_DAC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore page = CONC_DACCTL_PAGE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore offs = CONC_wDACFC_OFF;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_SYN:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore page = CONC_SYNCTL_PAGE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore offs = CONC_wSYNFC_OFF;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_ADC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore page = CONC_ADCCTL_PAGE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore offs = CONC_wADCFC_OFF;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note that the current frame counter is in the high nybble.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore frameno = audiopci_readmem(port->dev, page, offs) >> 16;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_exit(&dev->mutex);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore n = frameno >= port->frameno ?
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore frameno - port->frameno :
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore frameno + port->nframes - port->frameno;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->frameno = frameno;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->count += n;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = port->count;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_close(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_sync(void *arg, unsigned nframes)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(nframes));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->num == PORT_ADC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORCPU);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_sync(port->dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio_engine_ops_t audiopci_engine_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_ENGINE_VERSION, /* version number */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_open,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_close,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_start,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_stop,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_count,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_format,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_channels,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_rate,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_sync,
f9ead4a57883f3ef04ef20d83cc47987d98c0687Garrett D'Amore NULL,
f9ead4a57883f3ef04ef20d83cc47987d98c0687Garrett D'Amore NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint16_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_dac_rate(int samPerSec)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned short usTemp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* samPerSec /= 2; */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore usTemp = (unsigned short) ((DAC_CLOCK_DIVIDE / 8) / samPerSec);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (usTemp & 0x00000001) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore usTemp >>= 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore usTemp -= 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore usTemp >>= 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore usTemp -= 2;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (usTemp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_init_hw(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* setup DAC frequency */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(dev, CONC_wDACRATE_OFF, audiopci_dac_rate(48000));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CLR8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_CCB_INTRM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_SYN_44KHZ);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Turn on CODEC (UART and joystick left disabled) */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bDEVCTL_OFF);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_DEVCTL_SERR_DIS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CONC_DEVCTL_CODEC_EN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Reset the UART */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bUARTCSTAT_OFF, 0x00);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Disable NMI */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bNMIENA_OFF, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(dev, CONC_wNMISTAT_OFF, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Initialize serial interface */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERFMT_OFF,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CONC_PCM_SYN_STEREO | CONC_PCM_SYN_16BIT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Unmute codec */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CLR8(dev, CONC_bMISCCTL_OFF, CONC_MISCCTL_MUTE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* mixer initialization */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_idle(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* power/reset down the codec */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_RESET_PWRD, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* now powerup and bring out of reset */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_RESET_PWRD, 0x3);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_idle(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* enable PLL for DAC2 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_CLKSELECT, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* select input mixer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_ADSELECT, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* mark FM for output mixer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_OUT_SW1, CODEC_OUT_ENABLE_SYNTH);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_OUT_SW2, CODEC_OUT_ENABLE_WAVE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* initialize some reasonable values for the WAVE and SYNTH inputs */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_VOL_WAVE_L, 6);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_VOL_WAVE_R, 6);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_VOL_SYNTH_L, 6);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_VOL_SYNTH_R, 6);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* enable microphone phantom power */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (dev->micbias) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(dev, 2, CONC_DEVCTL_MICBIAS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_init(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev->micbias = 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_init_hw(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i <= PORT_MAX; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned caps;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned dmaflags;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore size_t rlen;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_cookie_t c;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned ccnt;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port = &dev->port[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->dev = dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (i) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_SYN:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_OUTPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->speed = 44100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_DAC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_OUTPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dmaflags = DDI_DMA_WRITE | DDI_DMA_CONSISTENT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->speed = 48000;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case PORT_ADC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_INPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dmaflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->speed = 48000;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->num = i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Allocate DMA resources.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_alloc_handle(dev->dip, &dma_attr, DDI_DMA_SLEEP,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, &port->dmah) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "port %d: dma handle allocation failed", i);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_mem_alloc(port->dmah, AUDIOPCI_BUF_LEN, &buf_attr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &rlen, &port->acch) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "port %d: dma memory allocation failed", i);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* ensure that the buffer is zeroed out properly */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bzero(port->kaddr, rlen);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_addr_bind_handle(port->dmah, NULL, port->kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIOPCI_BUF_LEN, dmaflags, DDI_DMA_SLEEP, NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &c, &ccnt) != DDI_DMA_MAPPED) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "port %d: dma binding failed", i);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->paddr = c.dmac_address;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Allocate and configure audio engine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->engine = audio_engine_alloc(&audiopci_engine_ops, caps);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->engine == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "port %d: audio_engine_alloc failed", i);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_set_private(port->engine, port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_add_engine(dev->adev, port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Register audio controls.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audiopci_add_controls(dev) == DDI_FAILURE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_register(dev->adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "unable to register with audio framework");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_destroy(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_destroy(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* free up ports, including DMA resources for ports */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i <= PORT_MAX; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_port_t *port = &dev->port[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->paddr != 0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_unbind_handle(port->dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->acch != NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_mem_free(&port->acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->dmah != NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_free_handle(&port->dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->engine != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_remove_engine(dev->adev, port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_free(port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (dev->acch != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_regs_map_free(&dev->acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_del_controls(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (dev->adev != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_free(dev->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(dev, sizeof (*dev));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_stereo(audiopci_dev_t *dev, audiopci_ctrl_num_t num, uint8_t lreg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t lval, rval;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t lmute, rmute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t rreg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rreg = lreg + 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = dev->controls[num].val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore lval = (val & 0xff00) >> 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rval = val & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore lmute = lval ? 0 : CODEC_ATT_MUTE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rmute = rval ? 0 : CODEC_ATT_MUTE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* convert to attenuation & apply mute if appropriate */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore lval = ((((100U - lval) * CODEC_ATT_MAX) / 100) & 0xff) | lmute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rval = ((((100U - rval) * CODEC_ATT_MAX) / 100) & 0xff) | rmute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, lreg, lval);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, rreg, rval);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_mono(audiopci_dev_t *dev, audiopci_ctrl_num_t num, uint8_t reg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val = (dev->controls[num].val & 0xff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t mute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mute = val ? 0 : CODEC_ATT_MUTE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = ((((100U - val) * CODEC_ATT_MAX) / 100) & 0xff) | mute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, reg, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_mono8(audiopci_dev_t *dev, audiopci_ctrl_num_t num, uint8_t reg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val = (dev->controls[num].val & 0xff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t mute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mute = val ? 0 : CODEC_ATT_MUTE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = ((((100U - val) * CODEC_ATT_MONO) / 100) & 0xff) | mute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, reg, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_get_value(void *arg, uint64_t *val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *val = pc->val;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_configure_output(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* PCM/Wave level */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_WAVE_L);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_WAVE_R);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_SYNTH_L);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono(dev, CTL_VOLUME, CODEC_VOL_SYNTH_R);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* front & mono outputs */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_stereo(dev, CTL_FRONT, CODEC_VOL_MASTER_L);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono8(dev, CTL_MONO, CODEC_VOL_MONO);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = dev->controls[CTL_MONSRC].val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* setup output monitoring as well */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = CODEC_OUT_ENABLE_SYNTH;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_MIC))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_OUT_ENABLE_MIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_CD))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_OUT_ENABLE_CD;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_LINEIN))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_OUT_ENABLE_AUX;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_OUT_SW1, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = CODEC_OUT_ENABLE_WAVE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_VIDEO))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_OUT_ENABLE_TV;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_PHONE))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_OUT_ENABLE_TAD;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_OUT_SW2, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_configure_input(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val = dev->controls[CTL_RECSRC].val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_LINEIN))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_AUX_L;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_CD))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_CD_L;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_MIC))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_MIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_PHONE))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_TAD;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_LIN_SW1, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_LINEIN))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_AUX_R;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_CD))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_CD_R;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_PHONE))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_TAD;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_MIC))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_MIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_RIN_SW1, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_VIDEO))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_TV_L;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_MIC))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_TMIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_LIN_SW2, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_VIDEO))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_TV_R;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & (1U << INPUT_MIC))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp |= CODEC_IN_ENABLE_TMIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_RIN_SW2, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* configure volumes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono(dev, CTL_MIC, CODEC_VOL_MIC);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_mono(dev, CTL_PHONE, CODEC_VOL_TAD);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_stereo(dev, CTL_LINE, CODEC_VOL_AUX_L);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_stereo(dev, CTL_CD, CODEC_VOL_CD_L);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_stereo(dev, CTL_VID, CODEC_VOL_TV_L);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* activate 30dB mic boost */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ak_write(dev, CODEC_MICBOOST,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev->controls[CTL_MICBOOST].val ? 1 : 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_reclevel(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t l;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t r;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = (val & 0xff00) >> 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = val & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((l > 100) || (r > 100))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_input(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_micboost(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_input(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_monsrc(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((val & ~INSRCS) != 0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_output(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_recsrc(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((val & ~INSRCS) != 0)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_input(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_volume(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val &= 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val > 100)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = (val & 0xff) | ((val & 0xff) << 8);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_output(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_front(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t l;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t r;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = (val & 0xff00) >> 8;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = val & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((l > 100) || (r > 100))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_output(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_set_speaker(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev = pc->dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val &= 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val > 100)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_output(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PLAYCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define RECCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define MONCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PCMVOL (PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define MAINVOL (PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define RECVOL (RECCTL | AUDIO_CTRL_FLAG_RECVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_alloc_ctrl(audiopci_dev_t *dev, uint32_t num, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_ctrl_desc_t desc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_ctrl_wr_t fn;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ctrl_t *pc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bzero(&desc, sizeof (desc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc = &dev->controls[num];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->num = num;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->dev = dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (num) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_VOLUME:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_VOLUME;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_MONO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = PCMVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_volume;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_FRONT:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_LINEOUT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = MAINVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_front;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_MONO:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_SPEAKER;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_MONO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = MAINVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_speaker;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_MIC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_MIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_MONO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_reclevel;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_LINE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_LINEIN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_reclevel;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_CD:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_CD;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_reclevel;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_VID:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_VIDEO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_reclevel;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_PHONE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_PHONE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_MONO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_reclevel;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_RECSRC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_RECSRC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = INSRCS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = INSRCS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECCTL | AUDIO_CTRL_FLAG_MULTI;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; audiopci_insrcs[i]; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_enum[i] = audiopci_insrcs[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_recsrc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_MONSRC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_MONSRC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = INSRCS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = INSRCS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = MONCTL | AUDIO_CTRL_FLAG_MULTI;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; audiopci_insrcs[i]; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_enum[i] = audiopci_insrcs[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_monsrc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_MICBOOST:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECCTL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiopci_set_micboost;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pc->ctrl = audio_dev_add_control(dev->adev, &desc,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_get_value, fn, pc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_add_controls(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_VOLUME, 75);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_FRONT, ((75) | (75 << 8)));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_MONO, 75);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_MIC, 50);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_LINE, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_CD, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_VID, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_PHONE, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_RECSRC, (1U << INPUT_MIC));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_MONSRC, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_alloc_ctrl(dev, CTL_MICBOOST, 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_output(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_configure_input(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_del_controls(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < CTL_NUM; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (dev->controls[i].ctrl) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_del_control(dev->controls[i].ctrl);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_attach(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t pci_command, vendor, device;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t pcih;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev = kmem_zalloc(sizeof (*dev), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev->dip = dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_set_driver_private(dip, dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_init(&dev->mutex, NULL, MUTEX_DRIVER, NULL);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev, "pci_config_setup failed");
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_destroy(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(dev, sizeof (*dev));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore vendor = pci_config_get16(pcih, PCI_CONF_VENID);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore device = pci_config_get16(pcih, PCI_CONF_DEVID);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((vendor != ENSONIQ_VENDOR_ID && vendor != CREATIVE_VENDOR_ID) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (device != ENSONIQ_ES1370))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto err_exit;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev->devid = device;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev->adev = audio_dev_alloc(dip, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (dev->adev == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto err_exit;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_description(dev->adev, "AudioPCI");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(dev->adev, "ES1370");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_add_info(dev->adev, "Legacy codec: Asahi Kasei AK4531");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* activate the device */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_command |= PCI_COMM_ME | PCI_COMM_IO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* map registers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_regs_map_setup(dip, 1, &dev->regs, 0, 0, &acc_attr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &dev->acch) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev, "can't map registers");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto err_exit;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* This allocates and configures the engines */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audiopci_init(dev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(dev->adev, "can't init device");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto err_exit;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_teardown(&pcih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_report_dev(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreerr_exit:
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_destroy(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_teardown(&pcih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_destroy(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_detach(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* first unregister us from the DDI framework, might be busy */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_unregister(dev->adev) != DDI_SUCCESS)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bSERCTL_OFF) &
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ~(CONC_SERCTL_DACIE | CONC_SERCTL_SYNIE | CONC_SERCTL_ADCIE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bDEVCTL_OFF) &
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ~(CONC_DEVCTL_DAC_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_SYN_EN);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&dev->mutex);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_destroy(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_resume(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* reinitialize hardware */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_init_hw(dev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_dev_resume(dev->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_suspend(audiopci_dev_t *dev)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_dev_suspend(dev->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_quiesce(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t tmp;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((dev = ddi_get_driver_private(dip)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* This disables all DMA engines and interrupts */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bSERCTL_OFF) &
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ~(CONC_SERCTL_DACIE | CONC_SERCTL_SYNIE | CONC_SERCTL_ADCIE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bSERCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore tmp = GET8(dev, CONC_bDEVCTL_OFF) &
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ~(CONC_DEVCTL_DAC_EN | CONC_DEVCTL_ADC_EN | CONC_DEVCTL_SYN_EN);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(dev, CONC_bDEVCTL_OFF, tmp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (cmd) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_ATTACH:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audiopci_attach(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_RESUME:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((dev = ddi_get_driver_private(dip)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audiopci_resume(dev));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiopci_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_dev_t *dev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((dev = ddi_get_driver_private(dip)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (cmd) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_DETACH:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audiopci_detach(dev));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_SUSPEND:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audiopci_suspend(dev));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct dev_ops audiopci_dev_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DEVO_REV, /* rev */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0, /* refcnt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* getinfo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nulldev, /* identify */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nulldev, /* probe */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ddi_attach, /* attach */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_ddi_detach, /* detach */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nodev, /* reset */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* cb_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* bus_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* power */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiopci_quiesce, /* quiesce */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modldrv audiopci_modldrv = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &mod_driverops, /* drv_modops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "Ensoniq 1370 Audio", /* linkinfo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &audiopci_dev_ops, /* dev_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modlinkage modlinkage = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore MODREV_1,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { &audiopci_modldrv, NULL }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore_init(void)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int rv;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_init_ops(&audiopci_dev_ops, DRVNAME);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = mod_install(&modlinkage)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&audiopci_dev_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (rv);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore_fini(void)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int rv;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = mod_remove(&modlinkage)) == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&audiopci_dev_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (rv);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore_info(struct modinfo *modinfop)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (mod_info(&modlinkage, modinfop));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}