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
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/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Purpose: Driver for the VIA8233/8235 AC97 audio controller
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/types.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/modctl.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/kmem.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/conf.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/ddi.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/sunddi.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/pci.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/note.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/audio/audio_driver.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/audio/ac97.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include "audiovia823x.h"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct ddi_device_acc_attr dev_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 struct ddi_device_acc_attr 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'Amorestatic ddi_dma_attr_t dma_attr_sgd = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DMA_ATTR_V0, /* version number */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000000, /* low DMA address range */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0xffffffff, /* high DMA address range */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000ffff, /* DMA counter register */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 8, /* DMA address alignment */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3c, /* DMA burstsizes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 8, /* min effective DMA size */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0xffffffff, /* max DMA xfer size */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000fff, /* segment boundary */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 1, /* s/g length */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 8, /* granularity of device */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0 /* Bus specific DMA flags */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic ddi_dma_attr_t dma_attr_buf = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DMA_ATTR_V0, /* version number */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000000, /* low DMA address range */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0xffffffff, /* high DMA address range */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0001fffe, /* DMA counter register */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 4, /* DMA address alignment */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3c, /* DMA burstsizes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 4, /* min effective DMA size */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0001ffff, /* max DMA xfer size */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0001ffff, /* segment boundary */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 1, /* s/g length */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 4, /* granularity of device */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0 /* Bus specific DMA flags */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_attach(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_resume(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_detach(auvia_devc_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_suspend(auvia_devc_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic int auvia_open(void *, int, unsigned *, caddr_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_close(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_start(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_stop(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_format(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_channels(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_rate(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint64_t auvia_count(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_sync(void *, unsigned);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint16_t auvia_read_ac97(void *, uint8_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_write_ac97(void *, uint8_t, uint16_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_alloc_port(auvia_devc_t *, int);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_reset_input(auvia_portc_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_reset_output(auvia_portc_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_destroy(auvia_devc_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void auvia_hwinit(auvia_devc_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic audio_engine_ops_t auvia_engine_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_ENGINE_VERSION,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_open,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_close,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_start,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_stop,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_count,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_format,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_channels,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_rate,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_sync,
f9ead4a57883f3ef04ef20d83cc47987d98c0687Garrett D'Amore NULL,
f9ead4a57883f3ef04ef20d83cc47987d98c0687Garrett D'Amore NULL,
f9ead4a57883f3ef04ef20d83cc47987d98c0687Garrett D'Amore NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint16_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_read_ac97(void *arg, uint8_t index)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t val = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = ((uint32_t)index << 16) | CODEC_RD;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTL(devc, devc->base + REG_CODEC, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(100);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Check AC CODEC access time out */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* if send command over, break */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (INL(devc, devc->base + REG_CODEC) & CODEC_STA_VALID)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(50);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (i == CODEC_TIMEOUT_COUNT) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto failed;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Check if Index still ours? If yes, return data, else return FAIL */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = INL(devc, devc->base + REG_CODEC);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTB(devc, devc->base + REG_CODEC + 3, 0x02);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (((val & CODEC_INDEX) >> 16) == index) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (val & CODEC_DATA);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorefailed:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0xffff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_write_ac97(void *arg, uint8_t index, uint16_t data)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t val = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = ((uint32_t)index << 16) | data | CODEC_WR;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTL(devc, devc->base + REG_CODEC, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(100);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Check AC CODEC access time out */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < CODEC_TIMEOUT_COUNT; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* if send command over, break */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!(INL(devc, devc->base + REG_CODEC) & CODEC_IN_CMD))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(50);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Audio routines
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amoreauvia_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(flag));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->count = 0;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore *nframesp = portc->nframes;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *bufp = portc->buf_kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_close(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_start(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = portc->devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->reset(portc);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore OUTB(devc, portc->base + OFF_CTRL, CTRL_START | CTRL_AUTOSTART);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_stop(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = portc->devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_format(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (AUDIO_FORMAT_S16_LE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_channels(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (portc->nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_rate(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (48000);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_sync(void *arg, unsigned nframes)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(nframes));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_sync(portc->buf_dmah, 0, 0, portc->syncdir);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreuint64_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_count(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = portc->devc;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint32_t pos;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint32_t n;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore pos = INL(devc, portc->base + OFF_COUNT);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore pos &= 0xffffff;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore pos /= (sizeof (int16_t) * portc->nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (pos >= portc->pos) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore n = portc->nframes - (pos - portc->pos);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore } else {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore n = portc->pos - pos;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore }
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->pos = pos;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->count += n;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore return (portc->count);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore/* private implementation bits */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_reset_output(auvia_portc_t *portc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = portc->devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t cmap;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->pos = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE); /* Stop */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTL(devc, portc->base + OFF_DMA, portc->sgd_paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTB(devc, portc->base + OFF_PLAYFMT,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PLAYFMT_16BIT | (portc->nchan << 4));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Select channel assignment - not valid for 8233A */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->chip_type != CHIP_8233A) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Undocumented slot mapping table:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * slot 3 = 1 (left)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * slot 4 = 2 (right)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * slot 6 = 5 (center)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * slot 9 = 6 (lfe)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * slot 7 = 3 (left rear)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * slot 8 = 4 (right rear)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (portc->nchan) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 1:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cmap = (1 << 0) | (1 << 4);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 2:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cmap = (1 << 0) | (2 << 4);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 4:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cmap = (1 << 0) | (2 << 4) | (3 << 8) | (4 << 12);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 6:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cmap = (1 << 0) | (2 << 4) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (5 << 8) | (6 << 12) | (3 << 16) | (4 << 20);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cmap = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTL(devc, portc->base + OFF_CHANNELS, cmap | 0xFF000000U);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_reset_input(auvia_portc_t *portc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc = portc->devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t fmt;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->pos = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE); /* Stop */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTL(devc, portc->base + OFF_DMA, portc->sgd_paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fmt = RECFMT_STEREO | RECFMT_16BIT;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->chip_type != CHIP_8233A) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fmt |= RECFMT_48K;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fmt |= (0xffU << 24);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTB(devc, portc->base + OFF_RECFIFO, RECFIFO_ENABLE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTL(devc, portc->base + OFF_RECFMT, fmt);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_alloc_port(auvia_devc_t *devc, int num)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore size_t len;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_cookie_t cookie;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint_t count;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int dir;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned caps;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t *desc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = devc->adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc = kmem_zalloc(sizeof (*portc), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->portc[num] = portc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->devc = devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (num) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUVIA_REC_SGD_NUM:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->base = devc->base + REG_RECBASE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->syncdir = DDI_DMA_SYNC_FORKERNEL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->nchan = 2;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->reset = auvia_reset_input;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_INPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dir = DDI_DMA_READ;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case AUVIA_PLAY_SGD_NUM:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->base = devc->base + REG_PLAYBASE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->syncdir = DDI_DMA_SYNC_FORDEV;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->nchan = 6;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->reset = auvia_reset_output;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_OUTPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dir = DDI_DMA_WRITE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure port is shut down */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore OUTB(portc->devc, portc->base + OFF_CTRL, CTRL_TERMINATE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->nframes = 4096;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore portc->buf_size = portc->nframes * portc->nchan * sizeof (int16_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* first allocate up space for SGD list */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_alloc_handle(devc->dip, &dma_attr_sgd,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_SLEEP, NULL, &portc->sgd_dmah) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed to allocate SGD handle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (ddi_dma_mem_alloc(portc->sgd_dmah, 2 * sizeof (uint32_t), &dev_attr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &portc->sgd_kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &len, &portc->sgd_acch) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed to allocate SGD memory");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_addr_bind_handle(portc->sgd_dmah, NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->sgd_kaddr, len, DDI_DMA_CONSISTENT | DDI_DMA_WRITE,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_SLEEP, NULL, &cookie, &count) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed binding SGD DMA handle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->sgd_paddr = cookie.dmac_address;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* now buffers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_alloc_handle(devc->dip, &dma_attr_buf, DDI_DMA_SLEEP, NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &portc->buf_dmah) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed to allocate BUF handle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_mem_alloc(portc->buf_dmah, portc->buf_size,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &buf_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &portc->buf_kaddr, &len, &portc->buf_acch) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed to allocate BUF memory");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_dma_addr_bind_handle(portc->buf_dmah, NULL, portc->buf_kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore len, DDI_DMA_CONSISTENT | dir, DDI_DMA_SLEEP, NULL, &cookie,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &count) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed binding BUF DMA handle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->buf_paddr = cookie.dmac_address;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /* now wire up descriptor -- just one */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc = (void *)portc->sgd_kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ddi_put32(portc->sgd_acch, desc++, portc->buf_paddr);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ddi_put32(portc->sgd_acch, desc++, AUVIA_SGD_EOL | portc->buf_size);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
505c7a699305ccafcfecc1ab0e7d4a25e2bfd1c2Garrett D'Amore (void) ddi_dma_sync(portc->sgd_dmah, 0, 0, DDI_DMA_SYNC_FORDEV);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore portc->engine = audio_engine_alloc(&auvia_engine_ops, caps);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->engine == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "audio_engine_alloc failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_set_private(portc->engine, portc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_add_engine(adev, portc->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_destroy(auvia_devc_t *devc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < AUVIA_NUM_PORTC; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = devc->portc[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!portc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore continue;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->engine) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_remove_engine(devc->adev, portc->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_free(portc->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->sgd_paddr) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_unbind_handle(portc->sgd_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->sgd_acch) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_mem_free(&portc->sgd_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->sgd_dmah) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_free_handle(&portc->sgd_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->buf_paddr) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_unbind_handle(portc->buf_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->buf_acch) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_mem_free(&portc->buf_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (portc->buf_dmah) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_free_handle(&portc->buf_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(portc, sizeof (*portc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->ac97 != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ac97_free(devc->ac97);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->adev != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_free(devc->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->regsh != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_regs_map_free(&devc->regsh);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->pcih != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_teardown(&devc->pcih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(devc, sizeof (*devc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_hwinit(auvia_devc_t *devc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t pcih = devc->pcih;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = pci_config_get32(pcih, AUVIA_PCICFG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* we want to disable all legacy */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val &= ~AUVIA_PCICFG_LEGACY;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val &= ~(AUVIA_PCICFG_FMEN | AUVIA_PCICFG_SBEN);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* enable AC'97 link and clear the reset bit */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val |= (AUVIA_PCICFG_ACLINKEN | AUVIA_PCICFG_NRST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* disable SRC (we won't use it) */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val &= ~AUVIA_PCICFG_SRCEN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* enable the SGD engines */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val |= AUVIA_PCICFG_SGDEN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put32(pcih, AUVIA_PCICFG, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_attach(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t pci_revision;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t pci_command, vendor, device;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t pcih;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore const char *version;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc = kmem_zalloc(sizeof (*devc), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->dip = dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_set_driver_private(dip, devc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((devc->adev = audio_dev_alloc(dip, 0)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cmn_err(CE_WARN, "audio_dev_alloc failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (pci_config_setup(dip, &pcih) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(devc->adev, "pci_config_setup failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->pcih = pcih;
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 if ((vendor != VIA_VENDOR_ID) || (device != VIA_8233_ID &&
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore device != VIA_8233A_ID)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(devc->adev, "Hardware not recognized "
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "(vendor=%x, dev=%x)", vendor, device);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->chip_type = CHIP_8233;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->chip_name = "VIA VT8233";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore version = "8233";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_revision = pci_config_get8(pcih, PCI_CONF_REVID);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (pci_revision == 0x50) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->chip_name = "VIA VT8235";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore version = "8235";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (pci_revision == 0x60) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->chip_name = "VIA VT8237";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore version = "8237";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((device == VIA_8233A_ID) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (device == VIA_8233_ID && pci_revision == 0x40)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->chip_type = CHIP_8233A;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->chip_name = "VIA VT8233A";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore version = "8233A";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_description(devc->adev, devc->chip_name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(devc->adev, version);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_command = pci_config_get16(pcih, PCI_CONF_COMM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_command |= PCI_COMM_ME | PCI_COMM_IO | PCI_COMM_MAE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put16(pcih, PCI_CONF_COMM, pci_command);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((ddi_regs_map_setup(dip, 1, &devc->base, 0, 0, &dev_attr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &devc->regsh)) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(devc->adev, "failed to map registers");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_hwinit(devc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((auvia_alloc_port(devc, AUVIA_PLAY_SGD_NUM) != DDI_SUCCESS) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (auvia_alloc_port(devc, AUVIA_REC_SGD_NUM) != DDI_SUCCESS)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc->ac97 = ac97_alloc(dip, auvia_read_ac97, auvia_write_ac97, devc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (devc->ac97 == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(devc->adev, "failed to allocate ac97 handle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ac97_init(devc->ac97, devc->adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(devc->adev, "failed to init ac97");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_register(devc->adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(devc->adev, "unable to register with framework");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_report_dev(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreerror:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_destroy(devc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_resume(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_hwinit(devc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ac97_reset(devc->ac97);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_dev_resume(devc->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_detach(auvia_devc_t *devc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_unregister(devc->adev) != DDI_SUCCESS)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_destroy(devc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_suspend(auvia_devc_t *devc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_dev_suspend(devc->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int auvia_ddi_quiesce(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct dev_ops auvia_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 auvia_ddi_attach, /* attach */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_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 auvia_ddi_quiesce, /* quiesce */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modldrv auvia_modldrv = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &mod_driverops, /* drv_modops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "Via 823x Audio", /* linkinfo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &auvia_dev_ops, /* dev_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modlinkage modlinkage = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore MODREV_1,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore { &auvia_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(&auvia_dev_ops, AUVIA_NAME);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = mod_install(&modlinkage)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&auvia_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(&auvia_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}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_ddi_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (cmd) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_ATTACH:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (auvia_attach(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_RESUME:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (auvia_resume(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (cmd) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_DETACH:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (auvia_detach(devc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_SUSPEND:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (auvia_suspend(devc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreauvia_ddi_quiesce(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_devc_t *devc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devc = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < AUVIA_NUM_PORTC; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore auvia_portc_t *portc = devc->portc[i];
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore OUTB(devc, portc->base + OFF_CTRL, CTRL_TERMINATE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}