/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Platform specifc code for the EB2 DMA controller. The EB2 is a PCI bus
* IC that includes play and record DMA engines and an interface for
* the CS4231.
*/
#include "audio_4231.h"
/*
* Attribute structure for the APC, used to create DMA handles.
*/
DMA_ATTR_V0, /* version */
0x0000000000000000LL, /* dlim_addr_lo */
0x00000000ffffffffLL, /* dlim_addr_hi */
0x0000000000ffffffLL, /* DMA counter register */
0x0000000000000001LL, /* DMA address alignment */
0x00000074, /* 4 and 16 byte burst sizes */
0x00000001, /* min effective DMA size */
0x000000000000ffffLL, /* maximum transfer size, 8k */
0x000000000000ffffLL, /* segment boundary, 32k */
0x00000001, /* s/g list length, no s/g */
0x00000001, /* granularity of device, don't care */
0 /* DMA flags */
};
};
};
/*
* DMA ops vector functions
*/
static int eb2_map_regs(CS_state_t *);
static void eb2_unmap_regs(CS_state_t *);
static void eb2_reset(CS_state_t *);
static int eb2_start_engine(CS_engine_t *);
static void eb2_stop_engine(CS_engine_t *);
static void eb2_power(CS_state_t *, int);
static void eb2_reload(CS_engine_t *);
"EB2 DMA controller",
};
/*
* eb2_map_regs()
*
* Description:
* This routine allocates the DMA handles and the memory for the
* DMA engines to use. It then binds each of the buffers to its
* respective handle, getting a DMA cookie. Finally, the registers
* are mapped in.
*
* NOTE: All of the ddi_dma_... routines sleep if they cannot get
* memory. This means these calls will almost always succeed.
*
* Arguments:
* CS_state_t *state The device's state
*
* Returns:
* DDI_SUCCESS Registers successfully mapped
* DDI_FAILURE Registers not successfully mapped
*/
static int
{
/* now, map the codec */
DDI_SUCCESS) {
goto error;
}
/* next the play registers */
DDI_SUCCESS) {
goto error;
}
/* now the capture registers */
DDI_SUCCESS) {
goto error;
}
/* finally the auxio register */
goto error;
}
/* disable play and record interrupts */
return (DDI_SUCCESS);
return (DDI_FAILURE);
} /* eb2_map_regs() */
/*
* eb2_unmap_regs()
*
* Description:
* This routine unmaps the Codec's and DMA engine's registers.
* It must be idempotent.
*
* Arguments:
* CS_state_t *state The device's state
*/
static void
{
if (CODEC_HANDLE)
if (EB2_PLAY_HNDL)
if (EB2_REC_HNDL)
if (EB2_AUXIO_HNDL)
} /* eb2_unmap_regs() */
/*
* eb2_reset()
*
* Description:
* Reset both the play and record DMA engines. The engines are left
* with interrupts and the DMA engine disabled.
*
* Arguments:
* dev_info_t *dip Pointer to the device's devinfo structure
* CS_state_t *state The device's state structure
*/
static void
{
int x;
/* start with the play side */
/* wait for play data to drain */
}
/* clear the reset bit and program for chaining */
/* now do the record side and program for chaining */
/* wait for record data to drain */
}
/* clear the reset bit */
} /* eb2_reset() */
/*
* eb2_start_engine()
*
* Description:
* This routine starts the DMA engine.
*
* NOTE: The state structure must be locked before this routine is called.
*
* Arguments:
* CS_engine_t *eng The DMA engine's state structure
*
* Returns:
* DDI_SUCCESS The DMA engine was started
* DDI_FAILURE The DMA engine was not started
*/
static int
{
int x;
} else {
}
/* reset the DMA engine so we have a good starting place */
/* wait for the FIFO to drain, it should be empty */
}
if (x >= CS4231_TIMEOUT) {
"timeout waiting for engine, not started!");
return (DDI_FAILURE);
}
/* now clear the RESET and EN_DMA bits */
/* put into chaining mode, enable byte counts */
/*
* Program the DMA engine.
*/
/*
* Start playing before we load the next fragment.
*/
/*
* Program the next address, too.
*/
return (DDI_SUCCESS);
} /* eb2_start_engine() */
/*
* eb2_stop_engine()
*
* Description:
* This routine stops the DMA engine.
*
* NOTE: The state structure must be locked before this routine is called.
*
* Arguments:
* CS_engine_t *eng The engine to stop
*/
static void
{
/* shut off DMA and disable interrupts */
drv_usecwait(1);
}
/* set the RESET bit to stop audio, also clear any TC interrupt */
/* wait for the FIFO to drain */
}
/* clear the RESET and EN_DMA bits */
} /* eb2_stop_engine() */
/*
* eb2_power()
*
* Description:
* This routine turns the Codec on or off using the auxio register
* in the eb2 device (cheerio or rio). Fortunately we don't need
* to delay like we do with the APC.
*
* NOTE: The state structure must be locked when this routine is called.
*
* Arguments:
* CS_state_t *state Ptr to the device's state structure
* int level Power level to set
*/
static void
{
} else { /* turn power off */
}
} /* eb2_power() */
/*
* eb2_reload()
*
* Description:
* This routine reloads the DMA address, so that we can continue
* double buffer round-robin fashion.
*
* Arguments:
* CS_engine_t *eng The engine
*/
static void
{
/* if next address already loaded, then we're done */
return;
}
/*
* For eb2 we first program the Next Byte Count Register.
*/
/* now program the Next Address Register */
}
/*
* eb2_addr()
*
* Description:
* This routine returns the current DMA address for the engine (the
* next address being accessed).
*
* Arguments:
* CS_engine_t *eng The engine
*
* Returns:
* Physical DMA address for current transfer.
*/
static uint32_t
{
}