audio1575.c revision cf6aa9d8704cb9a735d606653e386581e8a001bd
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 * Copyright 2009 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/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575 Audio Driver
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The driver is primarily targeted at providing audio support for
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * those systems which use the Uli M1575 audio core.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The M1575 audio core, in AC'97 controller mode, has independent
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * channels for PCM in, PCM out, mic in, modem in, and modem out.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The AC'97 controller is a PCI bus master with scatter/gather
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * support. Each channel has a DMA engine. Currently, we use only
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the PCM in and PCM out channels. Each DMA engine uses one buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * descriptor list. And the buffer descriptor list is an array of up
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * to 32 entries, each of which describes a data buffer. Each entry
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * contains a pointer to a data buffer, control bits, and the length
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * of the buffer being pointed to, where the length is expressed as
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the number of samples. This, combined with the 16-bit sample size,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * gives the actual physical length of the buffer.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NOTE:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This driver depends on the drv/audio, misc/ac97
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * modules being loaded first.
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#include "audio1575.h"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Module linkage routines for the kernel
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amorestatic int audio1575_ddi_quiesce(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Entry point routine prototypes
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_open(void *, int, unsigned *, unsigned *, caddr_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_close(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_start(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_stop(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_format(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_channels(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_rate(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint64_t audio1575_count(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_sync(void *, unsigned);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic size_t audio1575_qlen(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic audio_engine_ops_t audio1575_engine_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_ENGINE_VERSION,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_open,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_close,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_start,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_stop,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_count,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_format,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_channels,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_rate,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_sync,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_qlen
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * interrupt handler
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint_t audio1575_intr(caddr_t, caddr_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Local Routine Prototypes
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_attach(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_resume(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_detach(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_suspend(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amorestatic int audio1575_alloc_port(audio1575_state_t *, int, uint8_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_free_port(audio1575_port_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_start_port(audio1575_port_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_stop_port(audio1575_port_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_reset_port(audio1575_port_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_update_port(audio1575_port_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_setup_intr(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_codec_sync(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_write_ac97(void *, uint8_t, uint16_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint16_t audio1575_read_ac97(void *, uint8_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_chip_init(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audio1575_map_regs(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_unmap_regs(audio1575_state_t *);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amorestatic void audio1575_dma_stop(audio1575_state_t *, boolean_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_pci_enable(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_pci_disable(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audio1575_destroy(audio1575_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Global variables, but used only by this file.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI Structures
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Device operations structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct dev_ops audio1575_dev_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DEVO_REV, /* devo_rev */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0, /* devo_refcnt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* devo_getinfo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nulldev, /* devo_identify - obsolete */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nulldev, /* devo_probe */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_ddi_attach, /* devo_attach */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_ddi_detach, /* devo_detach */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore nodev, /* devo_reset */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* devi_cb_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* devo_bus_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, /* devo_power */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_ddi_quiesce, /* devo_quiesce */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Linkage structure for loadable drivers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modldrv audio1575_modldrv = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &mod_driverops, /* drv_modops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore M1575_MOD_NAME, /* drv_linkinfo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &audio1575_dev_ops, /* drv_dev_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Module linkage structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modlinkage audio1575_modlinkage = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore MODREV_1, /* ml_rev */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void *)&audio1575_modldrv, /* ml_linkage */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL /* NULL terminates the list */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * device access attributes for register mapping
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'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DMA attributes of buffer descriptor list
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic ddi_dma_attr_t bdlist_dma_attr = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DMA_ATTR_V0, /* version */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000000000000000LL, /* dlim_addr_lo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000000ffffffffLL, /* dlim_addr_hi */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x000000000000ffffLL, /* DMA counter register - 64 bits */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000000000000008LL, /* DMA address align must be 8-bytes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000003c, /* 1 through 64 byte burst sizes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000008, /* min xfer DMA size BDList entry */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000000000ffffLL, /* max xfer size, 64K */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x000000000001fffLL, /* seg, set to PAGESIZE */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000001, /* s/g list length, no s/g */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000008, /* granularity of device minxfer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0 /* DMA flags use virtual address */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DMA attributes of buffers to be used to receive/send audio data
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic ddi_dma_attr_t sample_buf_dma_attr = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DMA_ATTR_V0,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000000000000000LL, /* dlim_addr_lo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000000ffffffffLL, /* dlim_addr_hi */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x000000000001fffeLL, /* DMA counter register - 16 bits */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000000000000004LL, /* DMA address align 2-byte boundary */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0000003c, /* 1 through 60 byte burst sizes */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000004, /* min xfer DMA size BDList entry */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x000000000001ffffLL, /* max xfer size, 64K */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x000000000001ffffLL, /* seg, set to 64K */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000001, /* s/g list length, no s/g */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00000004, /* granularity of device minxfer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0 /* DMA flags use virtual address */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * _init()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Driver initialization, called when driver is first loaded.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is how access is initially given to all the static structures.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * None
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * mod_install() status, see mod_install(9f)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore_init(void)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_init_ops(&audio1575_dev_ops, M1575_NAME);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((error = mod_install(&audio1575_modlinkage)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&audio1575_dev_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (error);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * _fini()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Module de-initialization, called when the driver is to be unloaded.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * None
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * mod_remove() status, see mod_remove(9f)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore_fini(void)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((error = mod_remove(&audio1575_modlinkage)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (error);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* clean up ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&audio1575_dev_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * _info()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Module information, returns information about the driver.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * modinfo *modinfop Pointer to the opaque modinfo structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * mod_info() status, see mod_info(9f)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore_info(struct modinfo *modinfop)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (mod_info(&audio1575_modlinkage, modinfop));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* ******************* Driver Entry Points ********************************* */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_ddi_attach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implements the DDI attach(9e) entry point.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * ddi_attach_cmd_t cmd Attach command
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The driver was initialized properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE The driver couldn't be initialized properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_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 (audio1575_attach(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_RESUME:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audio1575_resume(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_ddi_detach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implements the detach(9e) entry point.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * ddi_detach_cmd_t cmd Detach command
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The driver was detached
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE The driver couldn't be detached
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_ddi_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (cmd) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_DETACH:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audio1575_detach(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_SUSPEND:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audio1575_suspend(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore/*
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * audio1575_ddi_quiesce()
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore *
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * Description:
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * Implements the quiesce(9e) entry point.
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore *
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * Arguments:
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore *
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * Returns:
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * DDI_SUCCESS The driver was quiesced
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * DDI_FAILURE The driver couldn't be quiesced
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amorestatic int
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amoreaudio1575_ddi_quiesce(dev_info_t *dip)
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore{
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_state_t *statep;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore if ((statep = ddi_get_driver_private(dip)) == NULL)
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore return (DDI_FAILURE);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_dma_stop(statep, B_TRUE);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore return (DDI_SUCCESS);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore}
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_intr()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Interrupt service routine for both play and record. For play we
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * get the next buffers worth of audio. For record we send it on to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the mixer.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Each of buffer descriptor has a field IOC(interrupt on completion)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * When both this and the IOC bit of correspondent dma control register
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * is set, it means that the controller should issue an interrupt upon
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * completion of this buffer. Note that in the clearing of the interrupts
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * below that the PCM IN and PCM out interrupts ar cleared by their
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * respective control registers and not by writing a '1' to the INTRSR
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the interrupt status register. Only CPRINTR,SPINTR,and GPIOINTR
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * require a '1' written to the INTRSR register to clear those
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * interrupts. See comments below.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * caddr_t arg Pointer to the interrupting device's state
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_INTR_CLAIMED Interrupt claimed and processed
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_INTR_UNCLAIMED Interrupt not claimed, and thus ignored
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_intr(caddr_t arg, caddr_t dontcare)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = (void *)arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t intrsr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t index;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *consume = NULL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *produce = NULL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(dontcare));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore intrsr = GET32(M1575_INTRSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* check if device is interrupting */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (intrsr == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->ksp) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* increment the spurious ino5 interrupt cnt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore M1575_KIOP(statep)->intrs[KSTAT_INTR_SPURIOUS]++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_INTR_UNCLAIMED);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* update the kernel interrupt statistics */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->ksp) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore M1575_KIOP(statep)->intrs[KSTAT_INTR_HARD]++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The Uli M1575 generates an interrupt for each interrupt
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * type. therefore we only process one interrupt type
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * per invocation of the audio1575_intr() routine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * WARNING: DO NOT attempt to optimize this by looping
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * until the INTRSR register is clear as this will
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * generate spurious ino5 interrupts.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (GET16(M1575_PCMISR_REG) & M1575_PCMISR_BCIS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Clear PCM IN interrupt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(M1575_PCMISR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note: This interrupt is not cleared by writing a '1'
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * to the M1575_INTRSR_REG according to the M1575 Super I/O
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * data sheet on page 189.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* update the LVI -- we just set it to the current value - 1 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore index = GET8(M1575_PCMICIV_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore index = (index - 1) % M1575_BD_NUMS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMILVIV_REG, index);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore produce = statep->ports[M1575_REC];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (GET16(M1575_PCMOSR_REG) & M1575_PCMOSR_BCIS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Clear PCM OUT interrupt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(M1575_PCMOSR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note: This interrupt is not cleared by writing a '1'
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * to the M1575_INTRSR_REG according to the M1575 Super I/O
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * data sheet on page 189.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* update the LVI -- we just set it to the current value - 1 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore index = GET8(M1575_PCMOCIV_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore index = (index - 1) % M1575_BD_NUMS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOLVIV_REG, index);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore consume = statep->ports[M1575_PLAY];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Clear other interrupts (there should not be any) */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_INTRSR_REG, (intrsr & M1575_INTR_MASK));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (produce) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_produce(produce->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (consume) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_consume(consume->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_INTR_CLAIMED);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_open()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Opens a DMA engine for use.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to set up
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * int flag Open flags
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * unsigned *fragfrp Receives number of frames per fragment
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * unsigned *nfragsp Receives number of fragments
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * caddr_t *bufp Receives kernel data buffer
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 on success
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * errno on failure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_open(void *arg, int flag,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned *fragfrp, unsigned *nfragsp, caddr_t *bufp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(flag));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->started = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->count = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *fragfrp = port->fragfr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *nfragsp = M1575_BD_NUMS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *bufp = port->samp_kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&port->statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_reset_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&port->statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_close()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Closes an audio DMA engine that was previously opened. Since
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * nobody is using it, we take this opportunity to possibly power
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * down the entire device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to shut down
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_close(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_stop_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->started = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_stop()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to stop a port that is
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * transferring data.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to stop
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_stop(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->started) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_stop_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->started = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_start()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to start a port transferring data.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to start
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 on success (never fails, errno if it did)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_start(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!port->started) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_start_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->started = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_format()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Called by the framework to query the format for the device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to query
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * AUDIO_FORMAT_S16_LE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_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'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_channels()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Called by the framework to query the channels for the device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to query
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Number of channels for the device
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_channels(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (port->nchan);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_rate()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Called by the framework to query the sample rate for the device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to query
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 48000
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_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'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_count()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to get the engine's frame counter
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to query
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * frame count for current engine
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint64_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_count(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_update_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = port->count + port->picb;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_sync()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to synchronize DMA caches.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to sync
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_sync(void *arg, unsigned nframes)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(nframes));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_sync(port->samp_dmah, 0, 0, port->sync_dir);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_qlen()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to determine on-device queue length.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The DMA engine to query
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * hardware queue length not reported by count (0 for this device)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic size_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_qlen(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_start_port()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine starts the DMA engine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_port_t *port Port of DMA engine to start.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_start_port(audio1575_port_t *port)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(mutex_owned(&statep->lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* if suspended, then do nothing else */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->suspended) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->num == M1575_REC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* ULi says do fifo resets here */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_FIFOCR1_REG, M1575_FIFOCR1_PCMIRST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CLR32(M1575_DMACR_REG, M1575_DMACR_PCMIPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMICR_REG, M1575_PCMICR_IOCE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PCMISTART);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CLR32(M1575_DMACR_REG, M1575_DMACR_PCMOPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOCR_REG, M1575_PCMOCR_IOCE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PCMOSTART);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_stop_port()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine stops the DMA engine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_port_t *port Port of DMA engine to stop.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_stop_port(audio1575_port_t *port)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(mutex_owned(&statep->lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* if suspended, then do nothing else */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->suspended) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->num == M1575_REC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PCMIPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PCMOPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_reset_port()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine resets the DMA engine pareparing it for work.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_port_t *port Port of DMA engine to reset.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_reset_port(audio1575_port_t *port)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(mutex_owned(&statep->lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->civ = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->picb = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->suspended)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->num == M1575_REC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Uli FIFO madness ... */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_FIFOCR1_REG, M1575_FIFOCR1_PCMIRST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PCMIPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMICR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMICR_REG, M1575_CR_RR | M1575_CR_IOCE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_PCMIBDBAR_REG, port->bdl_paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMILVIV_REG, M1575_BD_NUMS - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CLR32(M1575_DMACR_REG, M1575_DMACR_PCMIPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore uint32_t scr;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Uli FIFO madness ... */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_FIFOCR1_REG, M1575_FIFOCR1_PCMORST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PCMOPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore /* configure the number of channels properly */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore scr = GET32(M1575_SCR_REG);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore scr &= ~(M1575_SCR_6CHL_MASK | M1575_SCR_CHAMOD_MASK);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore scr |= M1575_SCR_6CHL_2; /* select our proper ordering */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore switch (port->nchan) {
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore case 2:
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore scr |= M1575_SCR_CHAMOD_2;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore break;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore case 4:
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore scr |= M1575_SCR_CHAMOD_4;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore break;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore case 6:
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore scr |= M1575_SCR_CHAMOD_6;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore break;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore }
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore PUT32(M1575_SCR_REG, scr);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOCR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOCR_REG, M1575_CR_RR | M1575_CR_IOCE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_PCMOBDBAR_REG, port->bdl_paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOLVIV_REG, M1575_BD_NUMS - 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CLR32(M1575_DMACR_REG, M1575_DMACR_PCMOPAUSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_update_port()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine updates the ports frame counter from hardware, and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * gracefully handles wraps.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_port_t *port The port to update.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_update_port(audio1575_port_t *port)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = port->statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t civ;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t picb;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned n;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int civoff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int picoff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->num == M1575_REC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore civoff = M1575_PCMICIV_REG;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore picoff = M1575_PCMIPICB_REG;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore civoff = M1575_PCMOCIV_REG;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore picoff = M1575_PCMOPICB_REG;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->suspended) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore civ = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore picb = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We read the position counters, but we're careful to avoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the situation where the position counter resets at the end
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * of a buffer.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < 2; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore civ = GET8(civoff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore picb = GET16(picoff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (GET8(civoff) == civ) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Chip did not start a new index, so
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the picb is valid.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (civ >= port->civ) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore n = civ - port->civ;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore n = civ + (M1575_BD_NUMS - port->civ);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->count += (n * port->fragfr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->civ = civ;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->picb = picb;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_attach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Attach an instance of the audio1575 driver. This routine does the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * device dependent attach tasks. When it is completed, it registers
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * with the audio framework.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The driver was initialized properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE The driver couldn't be initialized properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_attach(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t devid;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore const char *name;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore const char *rev;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore int maxch;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate the soft state structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_set_driver_private(dip, statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep->dip = dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We want the micboost enabled by default as well.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
cf6aa9d8704cb9a735d606653e386581e8a001bdGarrett D'Amore (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, AC97_PROP_MICBOOST, 1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate common audio dev structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = audio_dev_alloc(dip, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (adev == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(NULL, "unable to allocate audio dev");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep->adev = adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* map in the audio registers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio1575_map_regs(statep) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "couldn't map registers");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio1575_setup_intr(statep) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* message already noted */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Enable PCI I/O and Memory Spaces */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_pci_enable(statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore devid = (pci_config_get16(statep->pcih, PCI_CONF_VENID) << 16) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_get16(statep->pcih, PCI_CONF_DEVID);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (devid) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 0x10b95455:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore name = "Uli M1575 AC'97";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rev = "M5455";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore name = "Uli AC'97";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rev = "Unknown";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set device information -- this should check PCI config space */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_description(adev, name);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, rev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore statep->ac97 = ac97_alloc(dip, audio1575_read_ac97,
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_write_ac97, statep);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore ASSERT(statep->ac97 != NULL);
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore /*
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * Override "max-channels" property to prevent configuration
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * of 4 or 6 (or possibly even 8!) channel audio. The default
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * is to support as many channels as the hardware can do.
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore maxch = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore "max-channels", ac97_num_channels(statep->ac97));
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore if (maxch < 2) {
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore maxch = 2;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore }
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore statep->maxch = min(maxch, 6) & ~1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate port structures */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore if ((audio1575_alloc_port(statep, M1575_PLAY, statep->maxch) !=
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore DDI_SUCCESS) ||
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore (audio1575_alloc_port(statep, M1575_REC, 2) != DDI_SUCCESS)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio1575_chip_init(statep) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "failed to init chip");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ac97_init(statep->ac97, adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "ac'97 initialization failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set up kernel statistics */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((statep->ksp = kstat_create(M1575_NAME,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_get_instance(dip), M1575_NAME, "controller",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore KSTAT_TYPE_INTR, 1, KSTAT_FLAG_PERSISTENT)) != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kstat_install(statep->ksp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Enable PCI Interrupts */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(statep->pcih, M1575_PCIMISC_REG, M1575_PCIMISC_INTENB);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* enable audio interrupts */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_intr_enable(statep->ih) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "ddi_intr_enable() failure");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* register with the framework */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_register(adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "unable to register with framework");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* everything worked out, so report the device */
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 audio1575_destroy(statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_detach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Detach an instance of the audio1575 driver.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The driver was detached
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE The driver couldn't be detached
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_detach(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_unregister(statep->adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_destroy(statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* *********************** Local Routines *************************** */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_setup_intr()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine initializes the audio driver's interrupt handle and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * mutex.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Interrupt handle & mutex initialized
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE Interrupt handle & mutex not initialized
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_setup_intr(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint_t ipri;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int actual;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int rv;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int itype;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int count;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_intr_handle_t ih = NULL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dip = statep->dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = statep->adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* get supported interrupt types */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = ddi_intr_get_supported_types(dip, &itype);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv != DDI_SUCCESS) || (!(itype & DDI_INTR_TYPE_FIXED))) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "Fixed type interrupts not supported");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure we only have one fixed type interrupt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv != DDI_SUCCESS) || (count != 1)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "No fixed interrupts");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rv = ddi_intr_alloc(statep->dip, &ih, DDI_INTR_TYPE_FIXED,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0, 1, &actual, DDI_INTR_ALLOC_STRICT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv != DDI_SUCCESS) || (actual != 1)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "Can't alloc interrupt handle");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* test for a high level interrupt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_intr_get_pri(ih, &ipri) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "Can't get interrupt priority");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_intr_free(ih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ipri >= ddi_intr_get_hilevel_pri()) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "Unsupported high level interrupt");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_intr_free(ih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_intr_add_handler(ih, audio1575_intr, statep, NULL) !=
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "Can't add interrupt handler");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_intr_free(ih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep->ih = ih;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_init(&statep->lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_init(&statep->ac_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(ipri));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_alloc_port()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine allocates the DMA handles and the memory for the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DMA engines to use. It also configures the BDL lists properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * for use.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's devinfo
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * int num M1575_PLAY or M1575_REC
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore * uint8_t nchan Number of channels (2 = stereo, 6 = 5.1, etc.)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Registers successfully mapped
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE Registers not successfully mapped
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amoreaudio1575_alloc_port(audio1575_state_t *statep, int num, uint8_t nchan)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
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 char *prop;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t *kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t paddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int rc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = statep->adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dip = statep->dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port = kmem_zalloc(sizeof (*port), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep->ports[num] = port;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->num = num;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->statep = statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->started = B_FALSE;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore port->nchan = nchan;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (num == M1575_REC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore prop = "record-interrupts";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dir = DDI_DMA_READ;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_INPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->sync_dir = DDI_DMA_SYNC_FORKERNEL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore prop = "play-interrupts";
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dir = DDI_DMA_WRITE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_OUTPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->sync_dir = DDI_DMA_SYNC_FORDEV;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->intrs = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_PROP_DONTPASS, prop, M1575_INTS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure the values are good */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->intrs < M1575_MIN_INTS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "%s too low, %d, resetting to %d",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore prop, port->intrs, M1575_INTS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->intrs = M1575_INTS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (port->intrs > M1575_MAX_INTS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "%s too high, %d, resetting to %d",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore prop, port->intrs, M1575_INTS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->intrs = M1575_INTS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Figure out how much space we need. Sample rate is 48kHz, and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * we need to store 32 chunks. (Note that this means that low
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * interrupt frequencies will require more RAM. We could probably
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * do some cleverness to use a shorter BD list.)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->fragfr = 48000 / port->intrs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->fragfr = M1575_ROUNDUP(port->fragfr, M1575_MOD_SIZE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->samp_size = port->fragfr * port->nchan * 2;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->samp_size *= M1575_BD_NUMS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate dma handle */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_alloc_handle(dip, &sample_buf_dma_attr, DDI_DMA_SLEEP,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, &port->samp_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (rc != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "ddi_dma_alloc_handle failed: %d", rc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate DMA buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_mem_alloc(port->samp_dmah, port->samp_size, &buf_attr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &port->samp_kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &port->samp_size, &port->samp_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (rc == DDI_FAILURE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "dma_mem_alloc failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* bind DMA buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_addr_bind_handle(port->samp_dmah, NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->samp_kaddr, port->samp_size, dir|DDI_DMA_CONSISTENT,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_SLEEP, NULL, &cookie, &count);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "ddi_dma_addr_bind_handle failed: %d", rc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->samp_paddr = cookie.dmac_address;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * now, from here we allocate DMA memory for buffer descriptor list.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * we allocate adjacent DMA memory for all DMA engines.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_alloc_handle(dip, &bdlist_dma_attr, DDI_DMA_SLEEP,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, &port->bdl_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (rc != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "ddi_dma_alloc_handle(bdlist) failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * we allocate all buffer descriptors lists in continuous dma memory.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->bdl_size = sizeof (m1575_bd_entry_t) * M1575_BD_NUMS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_mem_alloc(port->bdl_dmah, port->bdl_size,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &port->bdl_kaddr, &port->bdl_size, &port->bdl_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (rc != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "ddi_dma_mem_alloc(bdlist) failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Wire up the BD list. We do this *before* binding the BD list
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * so that we don't have to do an extra ddi_dma_sync.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore paddr = port->samp_paddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kaddr = (void *)port->bdl_kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < M1575_BD_NUMS; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set base address of buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put32(port->bdl_acch, kaddr, paddr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kaddr++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set size in frames, and enable IOC interrupt */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put32(port->bdl_acch, kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((port->fragfr * port->nchan) | (1U << 31)));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kaddr++;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore paddr += (port->fragfr * port->nchan * 2);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_addr_bind_handle(port->bdl_dmah, NULL, port->bdl_kaddr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->bdl_size, DDI_DMA_WRITE|DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, &cookie, &count);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rc != DDI_DMA_MAPPED) || (count != 1)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "addr_bind_handle failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->bdl_paddr = cookie.dmac_address;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore port->engine = audio_engine_alloc(&audio1575_engine_ops, caps);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->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(port->engine, port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_add_engine(adev, port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_free_port()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine unbinds the DMA cookies, frees the DMA buffers,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * deallocates the DMA handles.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio810_port_t *port The port structure for a DMA engine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_free_port(audio1575_port_t *port)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port == NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->engine) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_remove_engine(port->statep->adev, port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_free(port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->bdl_paddr) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_unbind_handle(port->bdl_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->bdl_acch) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_mem_free(&port->bdl_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->bdl_dmah) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_free_handle(&port->bdl_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->samp_paddr) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_unbind_handle(port->samp_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->samp_acch) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_mem_free(&port->samp_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->samp_dmah) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_free_handle(&port->samp_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(port, sizeof (*port));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_map_regs()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The registers are mapped in.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's devinfo
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Registers successfully mapped
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE Registers not successfully mapped
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_map_regs(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip = statep->dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Check for fault management capabilities */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (DDI_FM_ACC_ERR_CAP(ddi_fm_capable(dip))) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_attr.devacc_attr_access = DDI_FLAGERR_ACC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* map the M1575 Audio PCI Cfg Space */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (pci_config_setup(dip, &statep->pcih) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(statep->adev, "PCI config map failure");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* map the M1575 Audio registers in PCI IO Space */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((ddi_regs_map_setup(dip, M1575_AUDIO_IO_SPACE, &statep->regsp,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0, 0, &dev_attr, &statep->regsh)) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(statep->adev, "Audio IO mapping failure");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreerror:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_unmap_regs(statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_unmap_regs()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine unmaps control registers.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_unmap_regs(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->regsh) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_regs_map_free(&statep->regsh);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->pcih) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_teardown(&statep->pcih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_chip_init()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine initializes the M1575 AC97 audio controller and the AC97
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * codec. The AC97 codec registers are programmed from codec_shadow[].
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If we are not doing a restore, we initialize codec_shadow[], otherwise
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * we use the current values of shadow. This routine expects that the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * PCI IO and Memory spaces have been mapped and enabled already.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * restore from codec_shadow[]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The hardware was initialized properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE The hardware couldn't be initialized properly
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_chip_init(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t ssr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t rtsr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t intrsr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int j;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore#ifdef __sparc
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t clk_detect;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t pcih;
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore#endif
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore clock_t ticks;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * clear the interrupt control and status register
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * READ/WRITE/READ workaround required
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * for buggy hardware
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_INTRCR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) GET32(M1575_INTRCR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore intrsr = GET32(M1575_INTRSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_INTRSR_REG, (intrsr & M1575_INTR_MASK));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) GET32(M1575_INTRSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ticks = drv_usectohz(M1575_LOOP_CTR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * SADA only supports stereo, so we set the channel bits
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * to "00" to select 2 channels.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * will also set the following:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Disable double rate enable
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * no SPDIF output selected
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 16 bit audio record mode
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 16 bit pcm out mode
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * PCM Out 6 chan mode FL FR CEN BL BR LFE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * PCM Out 2 channel mode (00)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < M1575_LOOP_CTR; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Reset the AC97 Codec and default to 2 channel 16 bit mode */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_SCR_REG, M1575_SCR_COLDRST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore delay(ticks<<1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Read the System Status Reg */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ssr = GET32(M1575_SSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure and release the blocked reset bit */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ssr & M1575_SSR_RSTBLK) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_INTFCR_REG, M1575_INTFCR_RSTREL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore delay(ticks);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Read the System Status Reg */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ssr = GET32(M1575_SSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure and release the blocked reset bit */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ssr & M1575_SSR_RSTBLK) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Reset the controller */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_SCR_REG, M1575_SCR_COLDRST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore delay(ticks);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* according AC'97 spec, wait for codec reset */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (j = 0; j < M1575_LOOP_CTR; j++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((GET32(M1575_SCR_REG) & M1575_SCR_COLDRST) == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore delay(ticks);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* codec reset failed */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (j >= M1575_LOOP_CTR) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(statep->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "failure to reset codec");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Wait for FACRDY First codec ready. The hardware can
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * provide the state of
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * codec ready bit on SDATA_IN[0] and as reflected in
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the Recv Tag Slot Reg.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rtsr = GET32(M1575_RTSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (rtsr & M1575_RTSR_FACRDY) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else { /* reset the status and wait for new status to set */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rtsr |= M1575_RTSR_FACRDY;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_RTSR_REG, rtsr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* if we could not reset the AC97 codec then report failure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (i >= M1575_LOOP_CTR) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(statep->adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "no codec ready signal received");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore#ifdef __sparc
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Magic code from ULi to Turn on the AC_LINK clock */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pcih = statep->pcih;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 4);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pci_config_get8(pcih, M1575_PCIACD_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 2);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore clk_detect = pci_config_get8(pcih, M1575_PCIACD_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (clk_detect != 1) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(statep->adev, "No AC97 Clock Detected");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore#endif
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Magic code from Uli to Init FIFO1 and FIFO2 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_FIFOCR1_REG, 0x81818181);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_FIFOCR2_REG, 0x81818181);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_FIFOCR3_REG, 0x81818181);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Make sure that PCM in and PCM out are enabled */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_INTFCR_REG, (M1575_INTFCR_PCMIENB | M1575_INTFCR_PCMOENB));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_dma_stop(statep, B_FALSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_dma_stop()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine is used to put each DMA engine into the quiet state.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *statep The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amoreaudio1575_dma_stop(audio1575_state_t *statep, boolean_t quiesce)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint32_t intrsr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->regsh == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* pause bus master (needed for the following reset register) */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < M1575_LOOP_CTR; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET32(M1575_DMACR_REG, M1575_DMACR_PAUSE_ALL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (GET32(M1575_DMACR_REG) & M1575_DMACR_PAUSE_ALL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (i >= M1575_LOOP_CTR) {
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore if (!quiesce)
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio_dev_warn(statep->adev, "failed to stop DMA");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Pause bus master (needed for the following reset register) */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMICR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOCR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_MICICR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_CSPOCR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMI2CR_RR, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_MICI2CR_RR, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Reset the bus master registers for all DMA engines */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMICR_REG, M1575_PCMICR_RR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMOCR_REG, M1575_PCMOCR_RR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_MICICR_REG, M1575_MICICR_RR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_CSPOCR_REG, M1575_CSPOCR_RR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_PCMI2CR_REG, M1575_PCMI2CR_RR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT8(M1575_MICI2CR_REG, M1575_MICI2CR_RR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Reset FIFOS */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_FIFOCR1_REG, 0x81818181);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_FIFOCR2_REG, 0x81818181);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_FIFOCR3_REG, 0x81818181);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Clear Interrupts */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(M1575_PCMISR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(M1575_PCMOSR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(M1575_MICISR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(M1575_CSPOSR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(M1575_PCMI2SR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SET16(M1575_MICI2SR_REG, M1575_SR_CLR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * clear the interrupt control and status register
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * READ/WRITE/READ workaround required
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * for buggy hardware
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_INTRCR_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) GET32(M1575_INTRCR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore intrsr = GET32(M1575_INTRSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_INTRSR_REG, (intrsr & M1575_INTR_MASK));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) GET32(M1575_INTRSR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_codec_sync()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Serialize access to the AC97 audio mixer registers.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Ready for an I/O access to the codec
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE An I/O access is currently in progress, can't
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * perform another I/O access.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_codec_sync(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* do the Uli Shuffle ... */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < M1575_LOOP_CTR; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Read the semaphore, and loop till we own it */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((GET32(M1575_CASR_REG) & 1) == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int j = 0; j < M1575_LOOP_CTR; j++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Wait for CWRSUCC 0x8 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (GET32(M1575_CSPSR_REG) &
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore M1575_CSPSR_SUCC) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(10);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_write_ac97()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the specific AC97 Codec register.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint8_t reg AC97 register number
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint16_t data The data want to be set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_write_ac97(void *arg, uint8_t reg, uint16_t data)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio1575_codec_sync(statep) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* write the data to WRITE to the lo word of the CPR register */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(M1575_CPR_REG, data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* write the address to WRITE to the hi word of the CPR register */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(M1575_CPR_REG+2, reg);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* wait until command is completed sucessfully */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < M1575_LOOP_CTR; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Wait for Write Ready 0x01 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (GET32(M1575_CSPSR_REG) & M1575_CSPSR_WRRDY) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (i < M1575_LOOP_CTR) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) audio1575_read_ac97(statep, reg);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_read_ac97()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Get the specific AC97 Codec register. It also updates codec_shadow[]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * with the register value.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint8_t reg AC97 register number
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Value of AC97 register. (0xffff in failure situations).
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint16_t
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_read_ac97(void *arg, uint8_t reg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t addr = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t data = 0xffff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((audio1575_codec_sync(statep)) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * at this point we have the CASR semaphore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and the codec is r/w ready
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * OR in the READ opcode into the address field
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore addr = (reg | M1575_CPR_READ);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* write the address to READ to the hi word of the CPR register */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT16(M1575_CPR_REG+2, addr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* wait until command is completed sucessfully */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < M1575_LOOP_CTR; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Wait for Read Ready 0x02 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (GET32(M1575_CSPSR_REG) & M1575_CSPSR_RDRDY) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (i < M1575_LOOP_CTR) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* read back the data and address */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore data = GET16(M1575_SPR_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore addr = GET16(M1575_SPR_REG+2);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (addr != reg) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore data = 0xffff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (data);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_pci_enable()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine Enables all PCI IO and MEMORY accesses
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *statep The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_pci_enable(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t pcics_reg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pcics_reg = pci_config_get16(statep->pcih, PCI_CONF_COMM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pcics_reg |= (PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put16(statep->pcih, PCI_CONF_COMM, pcics_reg);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_pci_disable()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine Disables all PCI IO and MEMORY accesses
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *statep The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_pci_disable(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint16_t pcics_reg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->pcih == NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pcics_reg = pci_config_get16(statep->pcih, PCI_CONF_COMM);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pcics_reg &= ~(PCI_COMM_IO | PCI_COMM_MAE | PCI_COMM_ME);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put16(statep->pcih, PCI_CONF_COMM, pcics_reg);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_resume()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Resume operation of the device after sleeping or hibernating.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note that this should never fail, even if hardware goes wonky,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * because the current PM framework will panic if it does.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The driver was resumed
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_resume(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* we've already allocated the state structure so get ptr */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = statep->adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(!mutex_owned(&statep->lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio1575_chip_init(statep) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Note that PM gurus say we should return
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * success here. Failure of audio shouldn't
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * be considered FATAL to the system. The
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * upshot is that audio will not progress.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "DDI_RESUME failed to init chip");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allow ac97 operations again */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ac97_resume(statep->ac97);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(statep->suspended);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep->suspended = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; i < M1575_NUM_PORTS; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_port_t *port = statep->ports[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* reset framework DMA engine buffer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->engine != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_reset(port->engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* reset and initialize hardware ports */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_reset_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (port->started) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_start_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_stop_port(port);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_suspend()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Suspend an instance of the audio1575 driver.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dev_info_t *dip Pointer to the device's dev_info struct
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The driver was suspended
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_suspend(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_state_t *statep;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ac97_suspend(statep->ac97);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore statep->suspended = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * stop all DMA operations
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_dma_stop(statep, B_FALSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_destroy()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine releases all resources held by the device instance,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * as part of either detach or a failure in attach.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio1575_state_t *state The device soft state.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * None
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudio1575_destroy(audio1575_state_t *statep)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t pcih;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* stop DMA engines */
0e7a77f3bec009d2e19415527920cc1c105cd24fGarrett D'Amore audio1575_dma_stop(statep, B_FALSE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->regsh != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* reset the codec */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUT32(M1575_SCR_REG, M1575_SCR_COLDRST);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((pcih = statep->pcih) != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* turn off the AC_LINK clock */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 4);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore pci_config_put8(pcih, M1575_PCIACD_REG, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Disable PCI I/O and Memory Spaces */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_pci_disable(statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->ih != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_intr_disable(statep->ih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_intr_remove_handler(statep->ih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_intr_free(statep->ih);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_destroy(&statep->lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_destroy(&statep->ac_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->ksp != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kstat_delete(statep->ksp);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_free_port(statep->ports[M1575_PLAY]);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_free_port(statep->ports[M1575_REC]);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio1575_unmap_regs(statep);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->ac97 != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ac97_free(statep->ac97);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (statep->adev != NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_free(statep->adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(statep, sizeof (*statep));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}