88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER START
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * The contents of this file are subject to the terms of the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Common Development and Distribution License (the "License").
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You may not use this file except in compliance with the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * or http://www.opensolaris.org/os/licensing.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * See the License for the specific language governing permissions
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and limitations under the License.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CDDL HEADER END
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Use is subject to license terms.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs Audio Driver
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This Audio Driver controls the Crystal CS4231 Codec used on many SPARC
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * platforms. It does not support the CS4231 on Power PCs or x86 PCs. It
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * does support two different DMA engines, the APC and EB2. The code for
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * those DMA engines is split out and a well defined, but private, interface
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * is used to control those DMA engines.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * For some reason setting the CS4231's registers doesn't always
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * succeed. Therefore every time we set a register we always read it
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * back to make sure it was set. If not we wait a little while and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * then try again. This is all taken care of in the routines
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_put_index() and audiocs_sel_index() and the macros ORIDX()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and ANDIDX(). We don't worry about the status register because it
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * is cleared by writing anything to it. So it doesn't matter what
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the value written is.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This driver supports suspending and resuming. A suspend just stops playing
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * and recording. The play DMA buffers end up getting thrown away, but when
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * you shut down the machine there is a break in the audio anyway, so they
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * won't be missed and it isn't worth the effort to save them. When we resume
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * we always start playing and recording. If they aren't needed they get
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * shut off by the mixer.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Power management is supported by this driver.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NOTE: This module depends on drv/audio being loaded first.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/modctl.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/kmem.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/stropts.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/ddi.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/sunddi.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/note.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include <sys/audio/audio_driver.h>
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#include "audio_4231.h"
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Module linkage routines for the kernel
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_ddi_attach(dev_info_t *, ddi_attach_cmd_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_ddi_detach(dev_info_t *, ddi_detach_cmd_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_ddi_power(dev_info_t *, int, int);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Entry point routine prototypes
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amorestatic int audiocs_open(void *, int, unsigned *, caddr_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_close(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_start(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_stop(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_format(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_channels(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_rate(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint64_t audiocs_count(void *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_sync(void *, unsigned);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Control callbacks.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_get_value(void *, uint64_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_set_ogain(void *, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_set_igain(void *, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_set_mgain(void *, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_set_inputs(void *, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_set_outputs(void *, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_set_micboost(void *, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Local Routines */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_resume(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_attach(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_detach(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_suspend(dev_info_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_destroy(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_init_state(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_chip_init(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_alloc_engine(CS_state_t *, int);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_free_engine(CS_engine_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_get_ports(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_configure_input(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_configure_output(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic CS_ctrl_t *audiocs_alloc_ctrl(CS_state_t *, uint32_t, uint64_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_free_ctrl(CS_ctrl_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_add_controls(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_del_controls(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_power_up(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_power_down(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int audiocs_poll_ready(CS_state_t *);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#ifdef DEBUG
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_put_index(CS_state_t *, uint8_t, uint8_t, int);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_sel_index(CS_state_t *, uint8_t, int);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define SELIDX(s, idx) audiocs_sel_index(s, idx, __LINE__)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PUTIDX(s, val, mask) audiocs_put_index(s, val, mask, __LINE__)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#else
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_put_index(CS_state_t *, uint8_t, uint8_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void audiocs_sel_index(CS_state_t *, uint8_t);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define SELIDX(s, idx) audiocs_sel_index(s, idx)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PUTIDX(s, val, mask) audiocs_put_index(s, val, mask)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore#define GETIDX(s) ddi_get8((handle), &CS4231_IDR)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define ORIDX(s, val, mask) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(s, \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (ddi_get8((handle), &CS4231_IDR) | (uint8_t)(val)), \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (uint8_t)(mask))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define ANDIDX(s, val, mask) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(s, (ddi_get8((handle), &CS4231_IDR) & (uint8_t)(val)), \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (uint8_t)(mask))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic audio_engine_ops_t audiocs_engine_ops = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_ENGINE_VERSION,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_open,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_close,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_start,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_stop,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_count,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_format,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_channels,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_rate,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_sync,
f9ead4a57883f3ef04ef20d83cc47987d98c0687Garrett D'Amore NULL,
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore NULL,
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore NULL,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define OUTPUT_SPEAKER 0
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define OUTPUT_HEADPHONES 1
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define OUTPUT_LINEOUT 2
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic const char *audiocs_outputs[] = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_SPEAKER,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_HEADPHONES,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_LINEOUT,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_MIC 0
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_LINEIN 1
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_STEREOMIX 2
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define INPUT_CD 3
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic const char *audiocs_inputs[] = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_MIC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_LINEIN,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_STEREOMIX,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore AUDIO_PORT_CD,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Global variables, but viewable only by this file.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* play gain array, converts linear gain to 64 steps of log10 gain */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic uint8_t cs4231_atten[] = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, /* [000] -> [004] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x3a, 0x39, 0x38, 0x37, 0x36, /* [005] -> [009] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x35, 0x34, 0x33, 0x32, 0x31, /* [010] -> [014] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x30, 0x2f, 0x2e, 0x2d, 0x2c, /* [015] -> [019] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x2b, 0x2a, 0x29, 0x29, 0x28, /* [020] -> [024] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x28, 0x27, 0x27, 0x26, 0x26, /* [025] -> [029] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x25, 0x25, 0x24, 0x24, 0x23, /* [030] -> [034] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x23, 0x22, 0x22, 0x21, 0x21, /* [035] -> [039] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x20, 0x20, 0x1f, 0x1f, 0x1f, /* [040] -> [044] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1e, 0x1e, 0x1e, 0x1d, 0x1d, /* [045] -> [049] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1d, 0x1c, 0x1c, 0x1c, 0x1b, /* [050] -> [054] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1b, 0x1b, 0x1a, 0x1a, 0x1a, /* [055] -> [059] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x1a, 0x19, 0x19, 0x19, 0x19, /* [060] -> [064] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x18, 0x18, 0x18, 0x18, 0x17, /* [065] -> [069] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x17, 0x17, 0x17, 0x16, 0x16, /* [070] -> [074] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x16, 0x16, 0x16, 0x15, 0x15, /* [075] -> [079] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x15, 0x15, 0x15, 0x14, 0x14, /* [080] -> [084] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x14, 0x14, 0x14, 0x13, 0x13, /* [085] -> [089] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x13, 0x13, 0x13, 0x12, 0x12, /* [090] -> [094] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x12, 0x12, 0x12, 0x12, 0x11, /* [095] -> [099] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x11, 0x11, 0x11, 0x11, 0x11, /* [100] -> [104] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x10, 0x10, 0x10, 0x10, 0x10, /* [105] -> [109] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x10, 0x0f, 0x0f, 0x0f, 0x0f, /* [110] -> [114] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, /* [114] -> [119] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, /* [120] -> [124] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, /* [125] -> [129] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, /* [130] -> [134] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, /* [135] -> [139] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, /* [140] -> [144] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, /* [145] -> [149] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x0a, 0x0a, 0x0a, 0x0a, 0x09, /* [150] -> [154] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x09, 0x09, 0x09, 0x09, 0x09, /* [155] -> [159] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x09, 0x09, 0x08, 0x08, 0x08, /* [160] -> [164] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x08, 0x08, 0x08, 0x08, 0x08, /* [165] -> [169] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x08, 0x07, 0x07, 0x07, 0x07, /* [170] -> [174] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x07, 0x07, 0x07, 0x07, 0x07, /* [175] -> [179] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x06, 0x06, 0x06, 0x06, 0x06, /* [180] -> [184] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x06, 0x06, 0x06, 0x06, 0x05, /* [185] -> [189] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x05, 0x05, 0x05, 0x05, 0x05, /* [190] -> [194] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x05, 0x05, 0x05, 0x05, 0x04, /* [195] -> [199] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x04, 0x04, 0x04, 0x04, 0x04, /* [200] -> [204] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x04, 0x04, 0x04, 0x04, 0x03, /* [205] -> [209] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x03, 0x03, 0x03, 0x03, 0x03, /* [210] -> [214] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x03, 0x03, 0x03, 0x03, 0x03, /* [215] -> [219] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x02, 0x02, 0x02, 0x02, 0x02, /* [220] -> [224] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x02, 0x02, 0x02, 0x02, 0x02, /* [225] -> [229] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x02, 0x01, 0x01, 0x01, 0x01, /* [230] -> [234] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x01, 0x01, 0x01, 0x01, 0x01, /* [235] -> [239] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x01, 0x01, 0x01, 0x00, 0x00, /* [240] -> [244] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00, 0x00, 0x00, 0x00, 0x00, /* [245] -> [249] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00, 0x00, 0x00, 0x00, 0x00, /* [250] -> [254] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore 0x00 /* [255] */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * STREAMS Structures
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI Structures
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Device operations structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct dev_ops audiocs_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 - not needed */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_ddi_attach, /* devo_attach */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_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 audiocs_ddi_power, /* devo_power */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_quiesce_not_supported, /* devo_quiesce */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Linkage structure for loadable drivers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modldrv audiocs_modldrv = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &mod_driverops, /* drv_modops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_MOD_NAME, /* drv_linkinfo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore &audiocs_dev_ops /* drv_dev_ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* Module linkage structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic struct modlinkage audiocs_modlinkage = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore MODREV_1, /* ml_rev */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void *)&audiocs_modldrv, /* ml_linkage */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL /* NULL terminates the list */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore};
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* ******* Loadable Module Configuration Entry Points ********************* */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * _init()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implements _init(9E).
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 rv;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_init_ops(&audiocs_dev_ops, CS4231_NAME);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = mod_install(&audiocs_modlinkage)) != 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&audiocs_dev_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (rv);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * _fini()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implements _fini(9E).
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 rv;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rv = mod_remove(&audiocs_modlinkage)) == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_fini_ops(&audiocs_dev_ops);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (rv);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * _info()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implements _info(9E).
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(&audiocs_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 * audiocs_ddi_attach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implement attach(9e).
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'Amoreaudiocs_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 (audiocs_attach(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_RESUME:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audiocs_resume(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_ddi_detach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implement detach(9e).
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 Success.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE Failure.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_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 (audiocs_detach(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case DDI_SUSPEND:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (audiocs_suspend(dip));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_ddi_power()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Implements power(9E).
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * def_info_t *dip Ptr to the device's dev_info structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * int component Which component to power up/down
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * int level The power level for the component
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Power level changed, we always succeed
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_ddi_power(dev_info_t *dip, int component, int level)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (component != CS4231_COMPONENT)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* get the state structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(!mutex_owned(&state->cs_lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure we have some work to do */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We don't do anything if we're suspended. Suspend/resume diddles
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * with power anyway.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (!state->cs_suspended) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* check the level change to see what we need to do */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (level == CS4231_PWR_OFF && state->cs_powered) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* power down and save the state */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_power_down(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_powered = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (level == CS4231_PWR_ON && !state->cs_powered) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* power up */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_power_up(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_powered = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(!mutex_owned(&state->cs_lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/* ******* Local Routines *************************************************** */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_destroy(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (state == NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = CS4231_PLAY; i <= CS4231_REC; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_engine(state->cs_engines[i]);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_del_controls(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (state->cs_adev) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_free(state->cs_adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* unmap the registers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_UNMAP_REGS(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* destroy the state mutex */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_destroy(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(state, sizeof (*state));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_attach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Attach an instance of the CS4231 driver. This routine does the device
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * dependent attach tasks. When it is complete it calls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio_dev_register() to register with the 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'Amoreaudiocs_attach(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate the state structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state = kmem_zalloc(sizeof (*state), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dip = dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_set_driver_private(dip, state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* now fill it in, initialize the state mutexs first */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mutex_init(&state->cs_lock, NULL, MUTEX_DRIVER, NULL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audio state initialization... should always succeed,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * framework will message failure.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((state->cs_adev = audio_dev_alloc(dip, 0)) == NULL) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_description(adev, CS_DEV_CONFIG_ONBRD1);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_add_info(adev, "Legacy codec: Crystal Semiconductor CS4231");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* initialize the audio state structures */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((audiocs_init_state(state)) == DDI_FAILURE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "init_state() failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore mutex_enter(&state->cs_lock);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* initialize the audio chip */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((audiocs_chip_init(state)) == DDI_FAILURE) {
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "chip_init() failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore goto error;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* chip init will have powered us up */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_powered = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* finally register with framework to kick everything off */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_register(state->cs_adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev, "unable to register audio dev");
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 audiocs_destroy(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_resume()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Resume a suspended device instance.
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'Amoreaudiocs_resume(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state;
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 state = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(dip == state->cs_dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(!mutex_owned(&state->cs_lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* mark the Codec busy -- this should keep power(9e) away */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_busy_component(state->cs_dip, CS4231_COMPONENT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* power it up */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_power_up(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_powered = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore mutex_enter(&state->cs_lock);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* initialize the audio chip */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((audiocs_chip_init(state)) == DDI_FAILURE) {
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "chip_init() failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_suspended = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We have already powered up the chip, but this alerts the
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * framework to the fact.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_raise_power(dip, CS4231_COMPONENT, CS4231_PWR_ON);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_dev_resume(state->cs_adev);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_detach()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Detach an instance of the CS4231 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 (busy)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_detach(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* get the state structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* don't detach if still in use */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audio_dev_unregister(adev) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (state->cs_powered) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Make sure the Codec and DMA engine are off.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, INTC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ANDIDX(state, ~(INTC_PEN|INTC_CEN), INTC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure the DMA engine isn't going to do anything */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_RESET(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * power down the device, no reason to waste power without
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * a driver
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_lower_power(dip, CS4231_COMPONENT, CS4231_PWR_OFF);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_destroy(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_suspend()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Suspend an instance of the CS4231 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'Amoreaudiocs_suspend(dev_info_t *dip)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* get the state structure */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state = ddi_get_driver_private(dip);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(!state->cs_suspended);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore audio_dev_suspend(state->cs_adev);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (state->cs_powered) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* now we can power down the Codec */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_power_down(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_powered = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_suspended = B_TRUE; /* stop new ops */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PLAYCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_PLAY)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define RECCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_REC)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define MONCTL (AUDIO_CTRL_FLAG_RW | AUDIO_CTRL_FLAG_MONITOR)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define PCMVOL (PLAYCTL | AUDIO_CTRL_FLAG_PCMVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define MAINVOL (PLAYCTL | AUDIO_CTRL_FLAG_MAINVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define RECVOL (RECCTL | AUDIO_CTRL_FLAG_RECVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define MONVOL (MONCTL | AUDIO_CTRL_FLAG_MONVOL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_alloc_ctrl
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Allocates a control structure for the audio mixer.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state Device soft state.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint32_t num Control number to allocate.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val Initial value.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Pointer to newly allocated CS_ctrl_t structure.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic CS_ctrl_t *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_alloc_ctrl(CS_state_t *state, uint32_t num, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_ctrl_desc_t desc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_ctrl_wr_t fn;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc = kmem_zalloc(sizeof (*cc), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_state = state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_num = num;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore bzero(&desc, sizeof (desc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (num) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_VOLUME:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_VOLUME;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = PCMVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiocs_set_ogain;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_IGAIN:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_RECGAIN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_STEREO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiocs_set_igain;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_MGAIN:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_MONGAIN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_MONO;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 100;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = MONVOL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiocs_set_mgain;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_INPUTS:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_RECSRC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = state->cs_imask;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = state->cs_imask;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECCTL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; audiocs_inputs[i]; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_enum[i] = audiocs_inputs[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiocs_set_inputs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_OUTPUTS:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_OUTPUTS;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_ENUM;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = state->cs_omod;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = state->cs_omask;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = PLAYCTL | AUDIO_CTRL_FLAG_MULTI;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (int i = 0; audiocs_outputs[i]; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_enum[i] = audiocs_outputs[i];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiocs_set_outputs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CTL_MICBOOST:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_name = AUDIO_CTRL_ID_MICBOOST;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_type = AUDIO_CTRL_TYPE_BOOLEAN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_minvalue = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_maxvalue = 1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore desc.acd_flags = RECCTL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore fn = audiocs_set_micboost;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_ctrl = audio_dev_add_control(state->cs_adev, &desc,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_get_value, fn, cc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (cc);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_free_ctrl
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Frees a control and all resources associated with it.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_ctrl_t *cc Pointer to control structure.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_free_ctrl(CS_ctrl_t *cc)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (cc == NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (cc->cc_ctrl)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_del_control(cc->cc_ctrl);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(cc, sizeof (*cc));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_add_controls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Allocates and registers all controls for this device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state Device soft state.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS All controls added and registered
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE At least one control was not added or registered.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_add_controls(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#define ADD_CTRL(CTL, ID, VAL) \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_##CTL = audiocs_alloc_ctrl(state, ID, VAL); \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (state->cs_##CTL == NULL) { \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev, \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "unable to allocate %s control", #ID); \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE); \
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ADD_CTRL(ogain, CTL_VOLUME, 0x4b4b);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ADD_CTRL(igain, CTL_IGAIN, 0x3232);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ADD_CTRL(mgain, CTL_MGAIN, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ADD_CTRL(micboost, CTL_MICBOOST, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ADD_CTRL(outputs, CTL_OUTPUTS, (state->cs_omask & ~state->cs_omod) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << OUTPUT_SPEAKER));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ADD_CTRL(inputs, CTL_INPUTS, (1U << INPUT_MIC));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_del_controls
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Unregisters and frees all controls for this device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state Device soft state.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_del_controls(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_ctrl(state->cs_ogain);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_ctrl(state->cs_igain);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_ctrl(state->cs_mgain);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_ctrl(state->cs_micboost);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_ctrl(state->cs_inputs);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_free_ctrl(state->cs_outputs);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_chip_init()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Power up the audio core, initialize the audio Codec, prepare the chip
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * for use.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Chip initialized and ready to use
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE Chip not initialized and not ready
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_chip_init(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* make sure we are powered up */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_POWER(state, CS4231_PWR_ON);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_RESET(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore /* wait for the Codec before we continue */
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore if (audiocs_poll_ready(state) == DDI_FAILURE) {
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore return (DDI_FAILURE);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore }
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* activate registers 16 -> 31 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, MID_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put8(handle, &CS4231_IDR, MID_MODE2);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* now figure out what version we have */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, VID_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_get8(handle, &CS4231_IDR) & VID_A) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_revA = B_TRUE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_revA = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* get rid of annoying popping by muting the output channels */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LDACO_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, LDACO_LDM | LDACO_MID_GAIN, LDAC0_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RDACO_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, RDACO_RDM | RDACO_MID_GAIN, RDAC0_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* initialize aux input channels to known gain values & muted */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LAUX1_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, LAUX1_LX1M | LAUX1_UNITY_GAIN, LAUX1_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RAUX1_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, RAUX1_RX1M | RAUX1_UNITY_GAIN, RAUX1_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LAUX2_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, LAUX2_LX2M | LAUX2_UNITY_GAIN, LAUX2_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RAUX2_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, RAUX2_RX2M | RAUX2_UNITY_GAIN, RAUX2_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* initialize aux input channels to known gain values & muted */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LLIC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, LLIC_LLM | LLIC_UNITY_GAIN, LLIC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RLIC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, RLIC_RLM | RLIC_UNITY_GAIN, RLIC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* program the sample rate, play and capture must be the same */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, FSDF_REG | IAR_MCE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, FS_48000 | PDF_LINEAR16NE | PDF_STEREO, FSDF_VALID_MASK);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore if (audiocs_poll_ready(state) == DDI_FAILURE) {
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore return (DDI_FAILURE);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore }
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, CDF_REG | IAR_MCE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, CDF_LINEAR16NE | CDF_STEREO, CDF_VALID_MASK);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore if (audiocs_poll_ready(state) == DDI_FAILURE) {
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore return (DDI_FAILURE);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set up the Codec for playback and capture disabled, dual DMA, and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * playback and capture DMA.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, (INTC_REG | IAR_MCE));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, INTC_DDC | INTC_PDMA | INTC_CDMA, INTC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audiocs_poll_ready(state) == DDI_FAILURE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Turn on the output level bit to be 2.8 Vpp. Also, don't go to 0 on
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * underflow.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, AFE1_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, AFE1_OLB, AFE1_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* turn on the high pass filter if Rev A */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, AFE2_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (state->cs_revA) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, AFE2_HPF, AFE2_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, 0, AFE2_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* clear the play and capture interrupt flags */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, AFS_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put8(handle, &CS4231_STATUS, (AFS_RESET_STATUS));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* the play and record gains will be set by the audio mixer */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* unmute the output */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LDACO_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ANDIDX(state, ~LDACO_LDM, LDAC0_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RDACO_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ANDIDX(state, ~RDACO_RDM, RDAC0_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* unmute the mono speaker and mute mono in */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, MIOC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, MIOC_MIM, MIOC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore audiocs_configure_output(state);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore audiocs_configure_input(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_init_state()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine initializes the audio driver's state structure and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * maps in the registers. This also includes reading the properties.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CAUTION: This routine maps the registers and initializes a mutex.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Failure cleanup is handled by cs4231_attach(). It is not
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * handled locally by this routine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS State structure initialized
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE State structure not initialized
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_init_state(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip = state->cs_dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore char *prop_str;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore char *pm_comp[] = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "NAME=audiocs audio device",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "0=off",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "1=on" };
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* set up the pm-components */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "pm-components", pm_comp, 3) != DDI_PROP_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "couldn't create pm-components property");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* figure out which DMA engine hardware we have */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "dma-model", &prop_str) == DDI_PROP_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (strcmp(prop_str, "eb2dma") == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dma_engine = EB2_DMA;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dma_ops = &cs4231_eb2dma_ops;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dma_engine = APC_DMA;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dma_ops = &cs4231_apcdma_ops;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_prop_free(prop_str);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dma_engine = APC_DMA;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_dma_ops = &cs4231_apcdma_ops;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* cs_regs, cs_eb2_regs and cs_handles filled in later */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* most of what's left is filled in when the registers are mapped */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_get_ports(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Allocate engines, must be done before register mapping called */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((audiocs_alloc_engine(state, CS4231_PLAY) != DDI_SUCCESS) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (audiocs_alloc_engine(state, CS4231_REC) != DDI_SUCCESS)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Map in the registers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (CS4231_DMA_MAP_REGS(state) == DDI_FAILURE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* Allocate and add controls, must be done *after* registers mapped */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (audiocs_add_controls(state) != DDI_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_suspended = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_powered = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_get_ports()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Get which audiocs h/w version we have and use this to
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * determine the input and output ports as well whether or not
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the hardware has internal loopbacks or not. We also have three
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * different ways for the properties to be specified, which we
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * also need to worry about.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Vers Platform(s) DMA eng. audio-module** loopback
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * a SS-4+/SS-5+ apcdma no no
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * b Ultra-1&2 apcdma no yes
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * c positron apcdma no yes
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * d PPC - retired
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * e x86 - retired
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * f tazmo eb2dma Perigee no
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * g tazmo eb2dma Quark yes
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * h darwin+ eb2dma no N/A
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Vers model~ aux1* aux2*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * a N/A N/A N/A
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * b N/A N/A N/A
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * c N/A N/A N/A
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * d retired
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * e retired
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * f SUNW,CS4231f N/A N/A
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * g SUNW,CS4231g N/A N/A
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * h SUNW,CS4231h cdrom none
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * * = Replaces internal-loopback for latest property type, can be
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * set to "cdrom", "loopback", or "none".
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * ** = For plugin audio modules only. Starting with darwin, this
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * property is replaces by the model property.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * ~ = Replaces audio-module.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * + = Has the capability of having a cable run from the internal
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CD-ROM to the audio device.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * N/A = Not applicable, the property wasn't created for early
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * platforms, or the property has been retired.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NOTE: Older tazmo and quark machines don't have the model property.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_get_ports(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip = state->cs_dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore char *prop_str;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* First we set the common ports, etc. */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_omask = state->cs_omod =
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << OUTPUT_SPEAKER) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << OUTPUT_HEADPHONES) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << OUTPUT_LINEOUT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_imask =
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << INPUT_MIC) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << INPUT_LINEIN) |
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (1U << INPUT_STEREOMIX);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* now we try the new "model" property */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "model", &prop_str) == DDI_PROP_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (strcmp(prop_str, "SUNW,CS4231h") == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* darwin */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, CS_DEV_VERSION_H);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_imask |= (1U << INPUT_CD);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_omod = (1U << OUTPUT_SPEAKER);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (strcmp(prop_str, "SUNW,CS4231g") == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* quark audio module */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, CS_DEV_VERSION_G);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NB: This could do SUNVTS LOOPBACK, but we
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * don't support it for now... owing to no
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * support in framework.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else if (strcmp(prop_str, "SUNW,CS4231f") == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* tazmo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, CS_DEV_VERSION_F);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, prop_str);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "unknown audio model: %s, some parts of "
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "audio may not work correctly", prop_str);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_prop_free(prop_str); /* done with the property */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else { /* now try the older "audio-module" property */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_PROP_DONTPASS, "audio-module", &prop_str) ==
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_PROP_SUCCESS) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (*prop_str) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 'Q': /* quark audio module */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, CS_DEV_VERSION_G);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* See quark comment above about SunVTS */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case 'P': /* tazmo */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, CS_DEV_VERSION_F);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, prop_str);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "unknown audio module: %s, some "
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "parts of audio may not work correctly",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore prop_str);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_prop_free(prop_str); /* done with the prop */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else { /* now try heuristics, ;-( */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_PROP_DONTPASS, "internal-loopback", B_FALSE)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (state->cs_dma_engine == EB2_DMA) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_DEV_VERSION_C);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_DEV_VERSION_B);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Again, we don't support SunVTS for these
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * boards, although we potentially could.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_set_version(adev, CS_DEV_VERSION_A);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_imask |= (1U << INPUT_CD);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_power_up()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Power up the Codec and restore the codec's registers.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NOTE: We don't worry about locking since the only routines
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * that may call us are attach() and power() Both of
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * which should be the only threads in the driver.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_power_up(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* turn on the Codec */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_POWER(state, CS4231_PWR_ON);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* reset the DMA engine(s) */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_RESET(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore (void) audiocs_poll_ready(state);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Reload the Codec's registers, the DMA engines will be
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * taken care of when play and record start up again. But
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * first enable registers 16 -> 31.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, MID_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, state->cs_save[MID_REG], MID_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < CS4231_REGS; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* restore Codec registers */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, (i | IAR_MCE));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put8(handle, &CS4231_IDR, state->cs_save[i]);
f275d02f08c70e13825071e2577d1481e8bba78eGarrett D'Amore (void) audiocs_poll_ready(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* clear MCE bit */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, 0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_power_down()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Power down the Codec and save the codec's registers.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * NOTE: See the note in cs4231_power_up() about locking.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_power_down(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int i;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore handle = state->cs_handles.cs_codec_hndl;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We are powering down, so we don't need to do a thing with
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * the DMA engines. However, we do need to save the Codec
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * registers.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (i = 0; i < CS4231_REGS; i++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* save Codec regs */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, i);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_save[i] = ddi_get8(handle, &CS4231_IDR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* turn off the Codec */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS4231_DMA_POWER(state, CS4231_PWR_OFF);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore} /* cs4231_power_down() */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_configure_input()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Configure input properties of the mixer (e.g. igain, ports).
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_configure_input(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t l, r;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t inputs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t micboost;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(mutex_owned(&state->cs_lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore inputs = state->cs_inputs->cc_val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore micboost = state->cs_micboost->cc_val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = (state->cs_igain->cc_val & 0xff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = ((state->cs_igain->cc_val & 0xff00) >> 8);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* rescale these for our atten array */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = (((uint32_t)l * 255) / 100) & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = (((uint32_t)r * 255) / 100) & 0xff;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* we downshift by 4 bits -- igain only has 16 possible values */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* NB: that we do not scale here! The SADA driver didn't do so. */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = l >> 4;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = r >> 4;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (inputs & (1U << INPUT_MIC)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l |= LADCI_LMIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r |= RADCI_RMIC;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (inputs & (1U << INPUT_LINEIN)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l |= LADCI_LLINE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r |= RADCI_RLINE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (inputs & (1U << INPUT_CD)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* note that SunVTS also uses this */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l |= LADCI_LAUX1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r |= RADCI_RAUX1;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (inputs & (1U << INPUT_STEREOMIX)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l |= LADCI_LLOOP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r |= RADCI_RLOOP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (micboost) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l |= LADCI_LMGE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r |= RADCI_RMGE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LADCI_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, l, LADCI_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RADCI_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, r, RADCI_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_configure_output()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Configure output properties of the mixer (e.g. ogain, mgain).
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic void
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_configure_output(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint64_t outputs;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t l, r;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t rmute, lmute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t mgain;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rmute = lmute = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(mutex_owned(&state->cs_lock));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore outputs = state->cs_outputs->cc_val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* port selection */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, MIOC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (outputs & (1U << OUTPUT_SPEAKER)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ANDIDX(state, ~MIOC_MONO_SPKR_MUTE, MIOC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ORIDX(state, MIOC_MONO_SPKR_MUTE, MIOC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, PC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (outputs & (1U << OUTPUT_HEADPHONES)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ANDIDX(state, ~PC_HEADPHONE_MUTE, PC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ORIDX(state, PC_HEADPHONE_MUTE, PC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, PC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (outputs & (1U << OUTPUT_LINEOUT)) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ANDIDX(state, ~PC_LINE_OUT_MUTE, PC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ORIDX(state, PC_LINE_OUT_MUTE, PC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* monitor gain */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mgain = cs4231_atten[((state->cs_mgain->cc_val * 255) / 100) & 0xff];
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LC_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (mgain == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* disable loopbacks when gain == 0 */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, LC_OFF, LC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore } else {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* we use cs4231_atten[] to linearize attenuation */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, (mgain << 2) | LC_LBE, LC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* output gain */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = ((state->cs_ogain->cc_val >> 8) & 0xff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = (state->cs_ogain->cc_val & 0xff);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (l == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore lmute = LDACO_LDM;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (r == 0) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rmute = RDACO_RDM;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* rescale these for our atten array */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore l = cs4231_atten[(((uint32_t)l * 255) / 100) & 0xff] | lmute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore r = cs4231_atten[(((uint32_t)r * 255) / 100) & 0xff] | rmute;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, LDACO_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, l, LDAC0_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, RDACO_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore PUTIDX(state, r, RDAC0_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_get_value()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Get a control value
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t *valp Pointer to store value.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been retrieved.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_get_value(void *arg, uint64_t *valp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *valp = cc->cc_val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_set_ogain()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the play gain.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val The gain to set (both left and right)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_set_ogain(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((val & ~0xffff) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((val & 0xff) > 100) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (((val & 0xff00) >> 8) > 100))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_configure_output(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_set_micboost()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the 20 dB microphone boost.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val The 1 to enable, 0 to disable.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_set_micboost(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = val ? B_TRUE : B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_configure_input(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_set_igain()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the record gain.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val The gain to set (both left and right)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_set_igain(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((val & ~0xffff) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ((val & 0xff) > 100) ||
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (((val & 0xff00) >> 8) > 100))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_configure_input(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_set_inputs()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the input ports.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val The mask of output ports.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_set_inputs(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (val & ~(state->cs_imask))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_configure_input(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_set_outputs()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the output ports.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val The mask of input ports.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_set_outputs(void *arg, uint64_t val)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((val & ~(state->cs_omod)) !=
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (state->cs_omask & ~state->cs_omod))
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = val;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_configure_output(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_set_mgain()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the monitor gain.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * void *arg The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint64_t val The gain to set (monoaural).)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 0 The Codec parameter has been set
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_set_mgain(void *arg, uint64_t gain)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_ctrl_t *cc = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = cc->cc_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (gain > 100)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (EINVAL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore cc->cc_val = gain;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audiocs_configure_output(state);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_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
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * unsigned *nframesp Receives number of frames
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
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amoreaudiocs_open(void *arg, int flag, unsigned *nframesp, caddr_t *bufp)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_engine_t *eng = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = eng->ce_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip = state->cs_dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(flag));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_busy_component(dip, CS4231_COMPONENT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (pm_raise_power(dip, CS4231_COMPONENT, CS4231_PWR_ON) ==
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_FAILURE) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* match the busy call above */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_idle_component(dip, CS4231_COMPONENT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev, "power up failed");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_count = 0;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore *nframesp = CS4231_NFRAMES;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *bufp = eng->ce_kaddr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (0);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_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'Amoreaudiocs_close(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_engine_t *eng = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = eng->ce_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) pm_idle_component(state->cs_dip, CS4231_COMPONENT);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_stop()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to stop an engine 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'Amoreaudiocs_stop(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS_engine_t *eng = arg;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS_state_t *state = eng->ce_state;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /*
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * Stop the DMA engine.
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS4231_DMA_STOP(state, eng);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /*
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * Stop the codec.
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore SELIDX(state, INTC_REG);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ANDIDX(state, ~(eng->ce_codec_en), INTC_VALID_MASK);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_start()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This is called by the framework to start an engine 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, an errno otherwise
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_start(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS_engine_t *eng = arg;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS_state_t *state = eng->ce_state;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint8_t mask;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint8_t value;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint8_t reg;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore int rv;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (eng->ce_num == CS4231_PLAY) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /* sample rate only set on play side */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore value = FS_48000 | PDF_STEREO | PDF_LINEAR16NE;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore reg = FSDF_REG;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mask = FSDF_VALID_MASK;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore } else {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore value = CDF_STEREO | CDF_LINEAR16NE;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore reg = CDF_REG;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore mask = CDF_VALID_MASK;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore eng->ce_curoff = 0;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore eng->ce_curidx = 0;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore SELIDX(state, reg | IAR_MCE);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore PUTIDX(state, value, mask);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (audiocs_poll_ready(state) != DDI_SUCCESS) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore rv = EIO;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore } else if (CS4231_DMA_START(state, eng) != DDI_SUCCESS) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore rv = EIO;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore } else {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /*
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * Start the codec.
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore SELIDX(state, INTC_REG);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ORIDX(state, eng->ce_codec_en, INTC_VALID_MASK);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore rv = 0;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore }
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (rv);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_format()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Called by the framework to query the format of 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_NE
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_format(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (AUDIO_FORMAT_S16_NE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_channels()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Called by the framework to query the channels of 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 * 2 (stereo)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorestatic int
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_channels(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(arg));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (2);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_rates()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Called by the framework to query the sample rate of 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'Amoreaudiocs_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 * audiocs_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'Amoreaudiocs_count(void *arg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS_engine_t *eng = arg;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS_state_t *state = eng->ce_state;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint64_t val;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore uint32_t off;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_enter(&state->cs_lock);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore off = CS4231_DMA_ADDR(state, eng);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore ASSERT(off >= eng->ce_paddr);
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore off -= eng->ce_paddr;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /*
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * Every now and then, we get a value that is just a wee bit
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * too large. This seems to be a small value related to
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * prefetch. Rather than believe it, we just assume the last
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * offset in the buffer. This should allow us to handle
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore * wraps, but without inserting bogus sample counts.
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (off >= CS4231_BUFSZ) {
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore off = CS4231_BUFSZ - 4;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore }
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore off /= 4;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore val = (off >= eng->ce_curoff) ?
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore off - eng->ce_curoff :
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore off + CS4231_NFRAMES - eng->ce_curoff;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore eng->ce_count += val;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore eng->ce_curoff = off;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val = eng->ce_count;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore /* while here, possibly reload the next address */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore CS4231_DMA_RELOAD(state, eng);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore mutex_exit(&state->cs_lock);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_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'Amoreaudiocs_sync(void *arg, unsigned nframes)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_engine_t *eng = arg;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore _NOTE(ARGUNUSED(nframes));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_sync(eng->ce_dmah, 0, 0, eng->ce_syncdir);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_alloc_engine()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Allocates the DMA handles and the memory for the DMA engine.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *dip Pointer to the device's soft state
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * int num Engine number, CS4231_PLAY or CS4231_REC.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS Engine initialized.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE Engine not initialized.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_alloc_engine(CS_state_t *state, int num)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore unsigned caps;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int dir;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int rc;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dev_info_t *dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_engine_t *eng;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint_t ccnt;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_cookie_t dmac;
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore size_t bufsz;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore static ddi_device_acc_attr_t buf_attr = {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DEVICE_ATTR_V0,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_NEVERSWAP_ACC,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_STRICTORDER_ACC
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore };
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dip = state->cs_dip;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng = kmem_zalloc(sizeof (*eng), KM_SLEEP);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_state = state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_started = B_FALSE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_num = num;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore switch (num) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CS4231_REC:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dir = DDI_DMA_READ;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_INPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_syncdir = DDI_DMA_SYNC_FORKERNEL;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_codec_en = INTC_CEN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore case CS4231_PLAY:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore dir = DDI_DMA_WRITE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore caps = ENGINE_OUTPUT_CAP;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_syncdir = DDI_DMA_SYNC_FORDEV;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_codec_en = INTC_PEN;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore default:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(eng, sizeof (*eng));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(adev, "bad engine number (%d)!", num);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore state->cs_engines[num] = eng;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* allocate dma handle */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore rc = ddi_dma_alloc_handle(dip, CS4231_DMA_ATTR(state), DDI_DMA_SLEEP,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore NULL, &eng->ce_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 */
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore rc = ddi_dma_mem_alloc(eng->ce_dmah, CS4231_BUFSZ, &buf_attr,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &eng->ce_kaddr,
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore &bufsz, &eng->ce_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(eng->ce_dmah, NULL,
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore eng->ce_kaddr, CS4231_BUFSZ, dir | DDI_DMA_CONSISTENT,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore DDI_DMA_SLEEP, NULL, &dmac, &ccnt);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if ((rc != DDI_DMA_MAPPED) || (ccnt != 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
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore eng->ce_paddr = dmac.dmac_address;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore eng->ce_engine = audio_engine_alloc(&audiocs_engine_ops, caps);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (eng->ce_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(eng->ce_engine, eng);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_add_engine(adev, eng->ce_engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_free_engine()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine fress the engine and all associated resources.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_engine_t *eng Engine to free.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_free_engine(CS_engine_t *eng)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore CS_state_t *state = eng->ce_state;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_t *adev = state->cs_adev;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (eng == NULL)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (eng->ce_engine) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_remove_engine(adev, eng->ce_engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_engine_free(eng->ce_engine);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
68c47f65208790c466e5e484f2293d3baed71c6aGarrett D'Amore if (eng->ce_paddr) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore (void) ddi_dma_unbind_handle(eng->ce_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (eng->ce_acch) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_mem_free(&eng->ce_acch);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (eng->ce_dmah) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_dma_free_handle(&eng->ce_dmah);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore kmem_free(eng, sizeof (*eng));
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_poll_ready()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * This routine waits for the Codec to complete its initialization
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * sequence and is done with its autocalibration.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Early versions of the Codec have a bug that can take as long as
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * 15 seconds to complete its initialization. For these cases we
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * use a timeout mechanism so we don't keep the machine locked up.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t *state The device's state structure
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Returns:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_SUCCESS The Codec is ready to continue
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * DDI_FAILURE The Codec isn't ready to continue
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreint
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_poll_ready(CS_state_t *state)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int x = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t iar;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t idr;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(state->cs_regs != NULL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ASSERT(handle != NULL);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /* wait for the chip to initialize itself */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore iar = ddi_get8(handle, &CS4231_IAR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore while ((iar & IAR_INIT) && x++ < CS4231_TIMEOUT) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(50);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore iar = ddi_get8(handle, &CS4231_IAR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (x >= CS4231_TIMEOUT) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore x = 0;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore /*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Now wait for the chip to complete its autocalibration.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Set the test register.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore SELIDX(state, ESI_REG);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idr = ddi_get8(handle, &CS4231_IDR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore while ((idr & ESI_ACI) && x++ < CS4231_TIMEOUT) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(50);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore idr = ddi_get8(handle, &CS4231_IDR);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (x >= CS4231_TIMEOUT) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_FAILURE);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore return (DDI_SUCCESS);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_sel_index()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Select a cs4231 register. The cs4231 has a hardware bug where a
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * register is not always selected the first time. We try and try
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * again until the proper register is selected or we time out and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * print an error message.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiohdl_t ahandle Handle to this device
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * ddi_acc_handle_t handle A handle to the device's registers
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint8_t addr The register address to program
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * int reg The register to select
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#ifdef DEBUG
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_sel_index(CS_state_t *state, uint8_t reg, int n)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#else
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_sel_index(CS_state_t *state, uint8_t reg)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int x;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t T;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *addr = &CS4231_IAR;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (x = 0; x < CS4231_RETRIES; x++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put8(handle, addr, reg);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore T = ddi_get8(handle, addr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (T == reg) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(1000);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (x == CS4231_RETRIES) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#ifdef DEBUG
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "line %d: Couldn't select index (0x%02x 0x%02x)", n,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#else
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "Couldn't select index (0x%02x 0x%02x)",
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore T, reg);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "audio may not work correctly until it is stopped and "
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "restarted");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore/*
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * audiocs_put_index()
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Description:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Program a cs4231 register. The cs4231 has a hardware bug where a
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * register is not programmed properly the first time. We program a value,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * then immediately read back the value and reprogram if nescessary.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * We do this until the register is properly programmed or we time out and
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * print an error message.
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore *
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * Arguments:
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * CS_state_t state Handle to this device
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * uint8_t mask Mask to not set reserved register bits
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore * int val The value to program
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore */
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amorevoid
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#ifdef DEBUG
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_put_index(CS_state_t *state, uint8_t val, uint8_t mask, int n)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#else
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amoreaudiocs_put_index(CS_state_t *state, uint8_t val, uint8_t mask)
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore{
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore int x;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t T;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_acc_handle_t handle = CODEC_HANDLE;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore uint8_t *addr = &CS4231_IDR;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore val &= mask;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore for (x = 0; x < CS4231_RETRIES; x++) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore ddi_put8(handle, addr, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore T = ddi_get8(handle, addr);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (T == val) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore break;
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore drv_usecwait(1000);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore if (x == CS4231_RETRIES) {
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#ifdef DEBUG
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "line %d: Couldn't set value (0x%02x 0x%02x)", n, T, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#else
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "Couldn't set value (0x%02x 0x%02x)", T, val);
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore#endif
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore audio_dev_warn(state->cs_adev,
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "audio may not work correctly until it is stopped and "
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore "restarted");
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore }
88447a05f537aabe9a1bc3d5313f22581ec992a7Garrett D'Amore}