/*
* au1550_ac97.c -- Sound driver for Alchemy Au1550 MIPS Internet Edge
* Processor.
*
* Copyright 2004 Embedded Edge, LLC
* dan@embeddededge.com
*
* Mostly copied from the au1000.c driver and some from the
* PowerMac dbdma driver.
* We assume the processor can do memory coherent DMA.
*
* Ported to 2.6 by Matt Porter <mporter@kernel.crashing.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#undef DEBUG
#include <linux/module.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/sound.h>
#include <linux/slab.h>
#include <linux/soundcard.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
#include <linux/ac97_codec.h>
#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
#include <asm/mach-au1x00/au1xxx_psc.h>
#include <asm/mach-au1x00/au1xxx_dbdma.h>
#include <asm/mach-au1x00/au1xxx.h>
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
/* misc stuff */
#define POLL_COUNT 0x50000
#define AC97_EXT_DACS (AC97_EXTID_SDAC | AC97_EXTID_CDAC | AC97_EXTID_LDAC)
/* The number of DBDMA ring descriptors to allocate. No sense making
* this too large....if you can't keep up with a few you aren't likely
* to be able to with lots of them, either.
*/
#define NUM_DBDMA_DESCRIPTORS 4
#define err(format, arg...) printk(KERN_ERR format "\n" , ## arg)
/* Boot options
* 0 = no VRA, 1 = use VRA if codec supports it
*/
static DEFINE_MUTEX(au1550_ac97_mutex);
static int vra = 1;
module_param(vra, bool, 0);
MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
static struct au1550_state {
/* soundcore stuff */
int dev_audio;
struct ac97_codec *codec;
unsigned codec_base_caps; /* AC'97 reg 00h, "Reset Register" */
unsigned codec_ext_caps; /* AC'97 reg 28h, "Extended Audio ID" */
int no_vra; /* do not use VRA */
spinlock_t lock;
struct mutex open_mutex;
struct mutex sem;
fmode_t open_mode;
wait_queue_head_t open_wait;
struct dmabuf {
u32 dmanr;
unsigned sample_rate;
unsigned src_factor;
unsigned sample_size;
int num_channels;
int dma_bytes_per_sample;
int user_bytes_per_sample;
int cnt_factor;
void *rawbuf;
unsigned buforder;
unsigned numfrag;
unsigned fragshift;
void *nextIn;
void *nextOut;
int count;
unsigned total_bytes;
unsigned error;
wait_queue_head_t wait;
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dma_fragsize;
unsigned dmasize;
unsigned dma_qcount;
/* OSS stuff */
unsigned mapped:1;
unsigned ready:1;
unsigned stopped:1;
unsigned ossfragshift;
int ossmaxfrags;
unsigned subdivision;
} dma_dac, dma_adc;
} au1550_state;
static unsigned
ld2(unsigned int x)
{
unsigned r = 0;
if (x >= 0x10000) {
x >>= 16;
r += 16;
}
if (x >= 0x100) {
x >>= 8;
r += 8;
}
if (x >= 0x10) {
x >>= 4;
r += 4;
}
if (x >= 4) {
x >>= 2;
r += 2;
}
if (x >= 2)
r++;
return r;
}
static void
au1550_delay(int msec)
{
if (in_interrupt())
return;
schedule_timeout_uninterruptible(msecs_to_jiffies(msec));
}
static u16
rdcodec(struct ac97_codec *codec, u8 addr)
{
struct au1550_state *s = codec->private_data;
unsigned long flags;
u32 cmd, val;
u16 data;
int i;
spin_lock_irqsave(&s->lock, flags);
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97STAT);
au_sync();
if (!(val & PSC_AC97STAT_CP))
break;
}
if (i == POLL_COUNT)
err("rdcodec: codec cmd pending expired!");
cmd = (u32)PSC_AC97CDC_INDX(addr);
cmd |= PSC_AC97CDC_RD; /* read command */
au_writel(cmd, PSC_AC97CDC);
au_sync();
/* now wait for the data
*/
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97STAT);
au_sync();
if (!(val & PSC_AC97STAT_CP))
break;
}
if (i == POLL_COUNT) {
err("rdcodec: read poll expired!");
data = 0;
goto out;
}
/* wait for command done?
*/
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97EVNT);
au_sync();
if (val & PSC_AC97EVNT_CD)
break;
}
if (i == POLL_COUNT) {
err("rdcodec: read cmdwait expired!");
data = 0;
goto out;
}
data = au_readl(PSC_AC97CDC) & 0xffff;
au_sync();
/* Clear command done event.
*/
au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
au_sync();
out:
spin_unlock_irqrestore(&s->lock, flags);
return data;
}
static void
wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
{
struct au1550_state *s = codec->private_data;
unsigned long flags;
u32 cmd, val;
int i;
spin_lock_irqsave(&s->lock, flags);
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97STAT);
au_sync();
if (!(val & PSC_AC97STAT_CP))
break;
}
if (i == POLL_COUNT)
err("wrcodec: codec cmd pending expired!");
cmd = (u32)PSC_AC97CDC_INDX(addr);
cmd |= (u32)data;
au_writel(cmd, PSC_AC97CDC);
au_sync();
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97STAT);
au_sync();
if (!(val & PSC_AC97STAT_CP))
break;
}
if (i == POLL_COUNT)
err("wrcodec: codec cmd pending expired!");
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97EVNT);
au_sync();
if (val & PSC_AC97EVNT_CD)
break;
}
if (i == POLL_COUNT)
err("wrcodec: read cmdwait expired!");
/* Clear command done event.
*/
au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
au_sync();
spin_unlock_irqrestore(&s->lock, flags);
}
static void
waitcodec(struct ac97_codec *codec)
{
u16 temp;
u32 val;
int i;
/* codec_wait is used to wait for a ready state after
* an AC97C_RESET.
*/
au1550_delay(10);
/* first poll the CODEC_READY tag bit
*/
for (i = 0; i < POLL_COUNT; i++) {
val = au_readl(PSC_AC97STAT);
au_sync();
if (val & PSC_AC97STAT_CR)
break;
}
if (i == POLL_COUNT) {
err("waitcodec: CODEC_READY poll expired!");
return;
}
/* get AC'97 powerdown control/status register
*/
temp = rdcodec(codec, AC97_POWER_CONTROL);
/* If anything is powered down, power'em up
*/
if (temp & 0x7f00) {
/* Power on
*/
wrcodec(codec, AC97_POWER_CONTROL, 0);
au1550_delay(100);
/* Reread
*/
temp = rdcodec(codec, AC97_POWER_CONTROL);
}
/* Check if Codec REF,ANL,DAC,ADC ready
*/
if ((temp & 0x7f0f) != 0x000f)
err("codec reg 26 status (0x%x) not ready!!", temp);
}
/* stop the ADC before calling */
static void
set_adc_rate(struct au1550_state *s, unsigned rate)
{
struct dmabuf *adc = &s->dma_adc;
struct dmabuf *dac = &s->dma_dac;
unsigned adc_rate, dac_rate;
u16 ac97_extstat;
if (s->no_vra) {
/* calc SRC factor
*/
adc->src_factor = ((96000 / rate) + 1) >> 1;
adc->sample_rate = 48000 / adc->src_factor;
return;
}
adc->src_factor = 1;
ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
rate = rate > 48000 ? 48000 : rate;
/* enable VRA
*/
wrcodec(s->codec, AC97_EXTENDED_STATUS,
ac97_extstat | AC97_EXTSTAT_VRA);
/* now write the sample rate
*/
wrcodec(s->codec, AC97_PCM_LR_ADC_RATE, (u16) rate);
/* read it back for actual supported rate
*/
adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE);
pr_debug("set_adc_rate: set to %d Hz\n", adc_rate);
/* some codec's don't allow unequal DAC and ADC rates, in which case
* writing one rate reg actually changes both.
*/
dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
if (dac->num_channels > 2)
wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, dac_rate);
if (dac->num_channels > 4)
wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, dac_rate);
adc->sample_rate = adc_rate;
dac->sample_rate = dac_rate;
}
/* stop the DAC before calling */
static void
set_dac_rate(struct au1550_state *s, unsigned rate)
{
struct dmabuf *dac = &s->dma_dac;
struct dmabuf *adc = &s->dma_adc;
unsigned adc_rate, dac_rate;
u16 ac97_extstat;
if (s->no_vra) {
/* calc SRC factor
*/
dac->src_factor = ((96000 / rate) + 1) >> 1;
dac->sample_rate = 48000 / dac->src_factor;
return;
}
dac->src_factor = 1;
ac97_extstat = rdcodec(s->codec, AC97_EXTENDED_STATUS);
rate = rate > 48000 ? 48000 : rate;
/* enable VRA
*/
wrcodec(s->codec, AC97_EXTENDED_STATUS,
ac97_extstat | AC97_EXTSTAT_VRA);
/* now write the sample rate
*/
wrcodec(s->codec, AC97_PCM_FRONT_DAC_RATE, (u16) rate);
/* I don't support different sample rates for multichannel,
* so make these channels the same.
*/
if (dac->num_channels > 2)
wrcodec(s->codec, AC97_PCM_SURR_DAC_RATE, (u16) rate);
if (dac->num_channels > 4)
wrcodec(s->codec, AC97_PCM_LFE_DAC_RATE, (u16) rate);
/* read it back for actual supported rate
*/
dac_rate = rdcodec(s->codec, AC97_PCM_FRONT_DAC_RATE);
pr_debug("set_dac_rate: set to %d Hz\n", dac_rate);
/* some codec's don't allow unequal DAC and ADC rates, in which case
* writing one rate reg actually changes both.
*/
adc_rate = rdcodec(s->codec, AC97_PCM_LR_ADC_RATE);
dac->sample_rate = dac_rate;
adc->sample_rate = adc_rate;
}
static void
stop_dac(struct au1550_state *s)
{
struct dmabuf *db = &s->dma_dac;
u32 stat;
unsigned long flags;
if (db->stopped)
return;
spin_lock_irqsave(&s->lock, flags);
au_writel(PSC_AC97PCR_TP, PSC_AC97PCR);
au_sync();
/* Wait for Transmit Busy to show disabled.
*/
do {
stat = au_readl(PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_TB) != 0);
au1xxx_dbdma_reset(db->dmanr);
db->stopped = 1;
spin_unlock_irqrestore(&s->lock, flags);
}
static void
stop_adc(struct au1550_state *s)
{
struct dmabuf *db = &s->dma_adc;
unsigned long flags;
u32 stat;
if (db->stopped)
return;
spin_lock_irqsave(&s->lock, flags);
au_writel(PSC_AC97PCR_RP, PSC_AC97PCR);
au_sync();
/* Wait for Receive Busy to show disabled.
*/
do {
stat = au_readl(PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_RB) != 0);
au1xxx_dbdma_reset(db->dmanr);
db->stopped = 1;
spin_unlock_irqrestore(&s->lock, flags);
}
static void
set_xmit_slots(int num_channels)
{
u32 ac97_config, stat;
ac97_config = au_readl(PSC_AC97CFG);
au_sync();
ac97_config &= ~(PSC_AC97CFG_TXSLOT_MASK | PSC_AC97CFG_DE_ENABLE);
au_writel(ac97_config, PSC_AC97CFG);
au_sync();
switch (num_channels) {
case 6: /* stereo with surround and center/LFE,
* slots 3,4,6,7,8,9
*/
ac97_config |= PSC_AC97CFG_TXSLOT_ENA(6);
ac97_config |= PSC_AC97CFG_TXSLOT_ENA(9);
case 4: /* stereo with surround, slots 3,4,7,8 */
ac97_config |= PSC_AC97CFG_TXSLOT_ENA(7);
ac97_config |= PSC_AC97CFG_TXSLOT_ENA(8);
case 2: /* stereo, slots 3,4 */
case 1: /* mono */
ac97_config |= PSC_AC97CFG_TXSLOT_ENA(3);
ac97_config |= PSC_AC97CFG_TXSLOT_ENA(4);
}
au_writel(ac97_config, PSC_AC97CFG);
au_sync();
ac97_config |= PSC_AC97CFG_DE_ENABLE;
au_writel(ac97_config, PSC_AC97CFG);
au_sync();
/* Wait for Device ready.
*/
do {
stat = au_readl(PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_DR) == 0);
}
static void
set_recv_slots(int num_channels)
{
u32 ac97_config, stat;
ac97_config = au_readl(PSC_AC97CFG);
au_sync();
ac97_config &= ~(PSC_AC97CFG_RXSLOT_MASK | PSC_AC97CFG_DE_ENABLE);
au_writel(ac97_config, PSC_AC97CFG);
au_sync();
/* Always enable slots 3 and 4 (stereo). Slot 6 is
* optional Mic ADC, which we don't support yet.
*/
ac97_config |= PSC_AC97CFG_RXSLOT_ENA(3);
ac97_config |= PSC_AC97CFG_RXSLOT_ENA(4);
au_writel(ac97_config, PSC_AC97CFG);
au_sync();
ac97_config |= PSC_AC97CFG_DE_ENABLE;
au_writel(ac97_config, PSC_AC97CFG);
au_sync();
/* Wait for Device ready.
*/
do {
stat = au_readl(PSC_AC97STAT);
au_sync();
} while ((stat & PSC_AC97STAT_DR) == 0);
}
/* Hold spinlock for both start_dac() and start_adc() calls */
static void
start_dac(struct au1550_state *s)
{
struct dmabuf *db = &s->dma_dac;
if (!db->stopped)
return;
set_xmit_slots(db->num_channels);
au_writel(PSC_AC97PCR_TC, PSC_AC97PCR);
au_sync();
au_writel(PSC_AC97PCR_TS, PSC_AC97PCR);
au_sync();
au1xxx_dbdma_start(db->dmanr);
db->stopped = 0;
}
static void
start_adc(struct au1550_state *s)
{
struct dmabuf *db = &s->dma_adc;
int i;
if (!db->stopped)
return;
/* Put two buffers on the ring to get things started.
*/
for (i=0; i<2; i++) {
au1xxx_dbdma_put_dest(db->dmanr, virt_to_phys(db->nextIn),
db->dma_fragsize, DDMA_FLAGS_IE);
db->nextIn += db->dma_fragsize;
if (db->nextIn >= db->rawbuf + db->dmasize)
db->nextIn -= db->dmasize;
}
set_recv_slots(db->num_channels);
au1xxx_dbdma_start(db->dmanr);
au_writel(PSC_AC97PCR_RC, PSC_AC97PCR);
au_sync();
au_writel(PSC_AC97PCR_RS, PSC_AC97PCR);
au_sync();
db->stopped = 0;
}
static int
prog_dmabuf(struct au1550_state *s, struct dmabuf *db)
{
unsigned user_bytes_per_sec;
unsigned bufs;
unsigned rate = db->sample_rate;
if (!db->rawbuf) {
db->ready = db->mapped = 0;
db->buforder = 5; /* 32 * PAGE_SIZE */
db->rawbuf = kmalloc((PAGE_SIZE << db->buforder), GFP_KERNEL);
if (!db->rawbuf)
return -ENOMEM;
}
db->cnt_factor = 1;
if (db->sample_size == 8)
db->cnt_factor *= 2;
if (db->num_channels == 1)
db->cnt_factor *= 2;
db->cnt_factor *= db->src_factor;
db->count = 0;
db->dma_qcount = 0;
db->nextIn = db->nextOut = db->rawbuf;
db->user_bytes_per_sample = (db->sample_size>>3) * db->num_channels;