1787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer/* 2787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * Driver for A2 audio system used in SGI machines 3787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * Copyright (c) 2008 Thomas Bogendoerfer <tsbogend@alpha.fanken.de> 4787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * 5787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * Based on OSS code from Ladislav Michl <ladis@linux-mips.org>, which 6787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * was based on code from Ulf Carlsson 7787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * 8787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * This program is free software; you can redistribute it and/or modify 9787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * it under the terms of the GNU General Public License version 2 as 10787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * published by the Free Software Foundation. 11787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * 12787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * This program is distributed in the hope that it will be useful, 13787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * but WITHOUT ANY WARRANTY; without even the implied warranty of 14787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * GNU General Public License for more details. 16787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * 17787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * You should have received a copy of the GNU General Public License 18787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * along with this program; if not, write to the Free Software 19787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * 21787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer */ 22787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <linux/kernel.h> 23787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <linux/init.h> 24787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <linux/interrupt.h> 25787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <linux/dma-mapping.h> 26787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <linux/platform_device.h> 27787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <linux/io.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 29787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 30787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <asm/sgi/hpc3.h> 31787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <asm/sgi/ip22.h> 32787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 33787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <sound/core.h> 34787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <sound/control.h> 35787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <sound/pcm.h> 36787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <sound/pcm-indirect.h> 37787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include <sound/initval.h> 38787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 39787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#include "hal2.h" 40787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 41787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ 42787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ 43787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 44787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfermodule_param(index, int, 0444); 45787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas BogendoerferMODULE_PARM_DESC(index, "Index value for SGI HAL2 soundcard."); 46787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfermodule_param(id, charp, 0444); 47787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas BogendoerferMODULE_PARM_DESC(id, "ID string for SGI HAL2 soundcard."); 48787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas BogendoerferMODULE_DESCRIPTION("ALSA driver for SGI HAL2 audio"); 49787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas BogendoerferMODULE_AUTHOR("Thomas Bogendoerfer"); 50787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas BogendoerferMODULE_LICENSE("GPL"); 51787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 52787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 53787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_BLOCK_SIZE 1024 54787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_BUF_SIZE 16384 55787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 56787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstruct hal2_pbus { 57787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hpc3_pbus_dmacregs *pbus; 58787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int pbusnr; 59787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int ctrl; /* Current state of pbus->pbdma_ctrl */ 60787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 61787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 62787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstruct hal2_desc { 63787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hpc_dma_desc desc; 64787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer u32 pad; /* padding */ 65787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 66787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 67787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstruct hal2_codec { 68787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_indirect pcm_indirect; 69787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_substream *substream; 70787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 71787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned char *buffer; 72787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_addr_t buffer_dma; 73787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_desc *desc; 74787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_addr_t desc_dma; 75787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int desc_count; 76787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_pbus pbus; 77787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int voices; /* mono/stereo */ 78787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int sample_rate; 79787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int master; /* Master frequency */ 80787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned short mod; /* MOD value */ 81787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned short inc; /* INC value */ 82787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 83787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 84787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_MIX_OUTPUT_ATT 0 85787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_MIX_INPUT_GAIN 1 86787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 87787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstruct snd_hal2 { 88787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_card *card; 89787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 90787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_ctl_regs *ctl_regs; /* HAL2 ctl registers */ 91787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_aes_regs *aes_regs; /* HAL2 aes registers */ 92787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_vol_regs *vol_regs; /* HAL2 vol registers */ 93787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_syn_regs *syn_regs; /* HAL2 syn registers */ 94787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 95787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec dac; 96787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec adc; 97787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 98787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 99787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_INDIRECT_WAIT(regs) while (hal2_read(®s->isr) & H2_ISR_TSTATUS); 100787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 101787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_READ_ADDR(addr) (addr | (1<<7)) 102787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define H2_WRITE_ADDR(addr) (addr) 103787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 104787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic inline u32 hal2_read(u32 *reg) 105787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 106787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return __raw_readl(reg); 107787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 108787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 109787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic inline void hal2_write(u32 val, u32 *reg) 110787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 111787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer __raw_writel(val, reg); 112787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 113787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 114787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 115787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic u32 hal2_i_read32(struct snd_hal2 *hal2, u16 addr) 116787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 117787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer u32 ret; 118787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_ctl_regs *regs = hal2->ctl_regs; 119787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 120787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_READ_ADDR(addr), ®s->iar); 121787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 122787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ret = hal2_read(®s->idr0) & 0xffff; 123787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_READ_ADDR(addr) | 0x1, ®s->iar); 124787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 125787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ret |= (hal2_read(®s->idr0) & 0xffff) << 16; 126787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return ret; 127787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 128787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 129787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_i_write16(struct snd_hal2 *hal2, u16 addr, u16 val) 130787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 131787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_ctl_regs *regs = hal2->ctl_regs; 132787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 133787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(val, ®s->idr0); 134787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr1); 135787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr2); 136787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr3); 137787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_WRITE_ADDR(addr), ®s->iar); 138787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 139787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 140787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 141787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_i_write32(struct snd_hal2 *hal2, u16 addr, u32 val) 142787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 143787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_ctl_regs *regs = hal2->ctl_regs; 144787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 145787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(val & 0xffff, ®s->idr0); 146787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(val >> 16, ®s->idr1); 147787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr2); 148787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr3); 149787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_WRITE_ADDR(addr), ®s->iar); 150787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 151787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 152787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 153787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_i_setbit16(struct snd_hal2 *hal2, u16 addr, u16 bit) 154787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 155787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_ctl_regs *regs = hal2->ctl_regs; 156787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 157787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_READ_ADDR(addr), ®s->iar); 158787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 159787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write((hal2_read(®s->idr0) & 0xffff) | bit, ®s->idr0); 160787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr1); 161787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr2); 162787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr3); 163787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_WRITE_ADDR(addr), ®s->iar); 164787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 165787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 166787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 167787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_i_clearbit16(struct snd_hal2 *hal2, u16 addr, u16 bit) 168787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 169787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_ctl_regs *regs = hal2->ctl_regs; 170787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 171787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_READ_ADDR(addr), ®s->iar); 172787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 173787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write((hal2_read(®s->idr0) & 0xffff) & ~bit, ®s->idr0); 174787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr1); 175787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr2); 176787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, ®s->idr3); 177787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_WRITE_ADDR(addr), ®s->iar); 178787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2_INDIRECT_WAIT(regs); 179787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 180787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 181787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_gain_info(struct snd_kcontrol *kcontrol, 182787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_ctl_elem_info *uinfo) 183787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 184787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 185787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer uinfo->count = 2; 186787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer uinfo->value.integer.min = 0; 187787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer switch ((int)kcontrol->private_value) { 188787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case H2_MIX_OUTPUT_ATT: 189787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer uinfo->value.integer.max = 31; 190787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 191787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case H2_MIX_INPUT_GAIN: 192787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer uinfo->value.integer.max = 15; 193787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 194787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 195787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 196787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 197787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 198787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_gain_get(struct snd_kcontrol *kcontrol, 199787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_ctl_elem_value *ucontrol) 200787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 201787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol); 202787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer u32 tmp; 203787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int l, r; 204787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 205787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer switch ((int)kcontrol->private_value) { 206787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case H2_MIX_OUTPUT_ATT: 207787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer tmp = hal2_i_read32(hal2, H2I_DAC_C2); 208787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (tmp & H2I_C2_MUTE) { 209787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer l = 0; 210787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer r = 0; 211787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } else { 212787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer l = 31 - ((tmp >> H2I_C2_L_ATT_SHIFT) & 31); 213787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer r = 31 - ((tmp >> H2I_C2_R_ATT_SHIFT) & 31); 214787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 215787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 216787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case H2_MIX_INPUT_GAIN: 217787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer tmp = hal2_i_read32(hal2, H2I_ADC_C2); 218787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer l = (tmp >> H2I_C2_L_GAIN_SHIFT) & 15; 219787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer r = (tmp >> H2I_C2_R_GAIN_SHIFT) & 15; 220787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 221787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 222787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ucontrol->value.integer.value[0] = l; 223787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ucontrol->value.integer.value[1] = r; 224787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 225787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 226787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 227787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 228787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_gain_put(struct snd_kcontrol *kcontrol, 229787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_ctl_elem_value *ucontrol) 230787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 231787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_kcontrol_chip(kcontrol); 232787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer u32 old, new; 233787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int l, r; 234787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 235787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer l = ucontrol->value.integer.value[0]; 236787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer r = ucontrol->value.integer.value[1]; 237787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 238787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer switch ((int)kcontrol->private_value) { 239787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case H2_MIX_OUTPUT_ATT: 240787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer old = hal2_i_read32(hal2, H2I_DAC_C2); 241787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new = old & ~(H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE); 242787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (l | r) { 243787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer l = 31 - l; 244787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer r = 31 - r; 245787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new |= (l << H2I_C2_L_ATT_SHIFT); 246787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new |= (r << H2I_C2_R_ATT_SHIFT); 247787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } else 248787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new |= H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE; 249787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write32(hal2, H2I_DAC_C2, new); 250787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 251787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case H2_MIX_INPUT_GAIN: 252787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer old = hal2_i_read32(hal2, H2I_ADC_C2); 253787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new = old & ~(H2I_C2_L_GAIN_M | H2I_C2_R_GAIN_M); 254787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new |= (l << H2I_C2_L_GAIN_SHIFT); 255787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer new |= (r << H2I_C2_R_GAIN_SHIFT); 256787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write32(hal2, H2I_ADC_C2, new); 257787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 258787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 259787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return old != new; 260787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 261787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 262787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct snd_kcontrol_new hal2_ctrl_headphone __devinitdata = { 263787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 264787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .name = "Headphone Playback Volume", 265787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 266787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .private_value = H2_MIX_OUTPUT_ATT, 267787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .info = hal2_gain_info, 268787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .get = hal2_gain_get, 269787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .put = hal2_gain_put, 270787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 271787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 272787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct snd_kcontrol_new hal2_ctrl_mic __devinitdata = { 273787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 274787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .name = "Mic Capture Volume", 275787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 276787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .private_value = H2_MIX_INPUT_GAIN, 277787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .info = hal2_gain_info, 278787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .get = hal2_gain_get, 279787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .put = hal2_gain_put, 280787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 281787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 282787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int __devinit hal2_mixer_create(struct snd_hal2 *hal2) 283787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 284787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 285787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 286787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* mute DAC */ 287787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write32(hal2, H2I_DAC_C2, 288787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer H2I_C2_L_ATT_M | H2I_C2_R_ATT_M | H2I_C2_MUTE); 289787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* mute ADC */ 290787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write32(hal2, H2I_ADC_C2, 0); 291787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 292787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = snd_ctl_add(hal2->card, 293787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_ctl_new1(&hal2_ctrl_headphone, hal2)); 294787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) 295787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 296787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 297787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = snd_ctl_add(hal2->card, 298787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_ctl_new1(&hal2_ctrl_mic, hal2)); 299787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) 300787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 301787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 302787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 303787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 304787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 305787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic irqreturn_t hal2_interrupt(int irq, void *dev_id) 306787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 307787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = dev_id; 308787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer irqreturn_t ret = IRQ_NONE; 309787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 310787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* decide what caused this interrupt */ 311787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (hal2->dac.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) { 312787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_period_elapsed(hal2->dac.substream); 313787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ret = IRQ_HANDLED; 314787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 315787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (hal2->adc.pbus.pbus->pbdma_ctrl & HPC3_PDMACTRL_INT) { 316787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_period_elapsed(hal2->adc.substream); 317787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ret = IRQ_HANDLED; 318787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 319787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return ret; 320787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 321787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 322787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_compute_rate(struct hal2_codec *codec, unsigned int rate) 323787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 324787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned short mod; 325787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 326787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (44100 % rate < 48000 % rate) { 327787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer mod = 4 * 44100 / rate; 328787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->master = 44100; 329787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } else { 330787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer mod = 4 * 48000 / rate; 331787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->master = 48000; 332787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 333787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 334787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->inc = 4; 335787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->mod = mod; 336787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer rate = 4 * codec->master / mod; 337787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 338787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return rate; 339787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 340787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 341787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_set_dac_rate(struct snd_hal2 *hal2) 342787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 343787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int master = hal2->dac.master; 344787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int inc = hal2->dac.inc; 345787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int mod = hal2->dac.mod; 346787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 347787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write16(hal2, H2I_BRES1_C1, (master == 44100) ? 1 : 0); 348787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write32(hal2, H2I_BRES1_C2, 349787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ((0xffff & (inc - mod - 1)) << 16) | inc); 350787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 351787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 352787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_set_adc_rate(struct snd_hal2 *hal2) 353787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 354787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int master = hal2->adc.master; 355787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int inc = hal2->adc.inc; 356787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int mod = hal2->adc.mod; 357787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 358787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write16(hal2, H2I_BRES2_C1, (master == 44100) ? 1 : 0); 359787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write32(hal2, H2I_BRES2_C2, 360787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer ((0xffff & (inc - mod - 1)) << 16) | inc); 361787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 362787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 363787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_setup_dac(struct snd_hal2 *hal2) 364787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 365787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int fifobeg, fifoend, highwater, sample_size; 366787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_pbus *pbus = &hal2->dac.pbus; 367787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 368787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Now we set up some PBUS information. The PBUS needs information about 369787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * what portion of the fifo it will use. If it's receiving or 370787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * transmitting, and finally whether the stream is little endian or big 371787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * endian. The information is written later, on the start call. 372787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer */ 373787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer sample_size = 2 * hal2->dac.voices; 374787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Fifo should be set to hold exactly four samples. Highwater mark 375787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * should be set to two samples. */ 376787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer highwater = (sample_size * 2) >> 1; /* halfwords */ 377787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer fifobeg = 0; /* playback is first */ 378787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer fifoend = (sample_size * 4) >> 3; /* doublewords */ 379787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_LD | 380787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (highwater << 8) | (fifobeg << 16) | (fifoend << 24); 381787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* We disable everything before we do anything at all */ 382787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; 383787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); 384787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Setup the HAL2 for playback */ 385787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_set_dac_rate(hal2); 386787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Set endianess */ 387787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECTX); 388787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Set DMA bus */ 389787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr)); 390787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* We are using 1st Bresenham clock generator for playback */ 391787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write16(hal2, H2I_DAC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT) 392787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer | (1 << H2I_C1_CLKID_SHIFT) 393787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer | (hal2->dac.voices << H2I_C1_DATAT_SHIFT)); 394787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 395787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 396787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_setup_adc(struct snd_hal2 *hal2) 397787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 398787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned int fifobeg, fifoend, highwater, sample_size; 399787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_pbus *pbus = &hal2->adc.pbus; 400787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 401787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer sample_size = 2 * hal2->adc.voices; 402787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer highwater = (sample_size * 2) >> 1; /* halfwords */ 403787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer fifobeg = (4 * 4) >> 3; /* record is second */ 404787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer fifoend = (4 * 4 + sample_size * 4) >> 3; /* doublewords */ 405787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->ctrl = HPC3_PDMACTRL_RT | HPC3_PDMACTRL_RCV | HPC3_PDMACTRL_LD | 406787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (highwater << 8) | (fifobeg << 16) | (fifoend << 24); 407787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; 408787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_clearbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); 409787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Setup the HAL2 for record */ 410787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_set_adc_rate(hal2); 411787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Set endianess */ 412787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_clearbit16(hal2, H2I_DMA_END, H2I_DMA_END_CODECR); 413787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* Set DMA bus */ 414787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_setbit16(hal2, H2I_DMA_DRV, (1 << pbus->pbusnr)); 415787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* We are using 2nd Bresenham clock generator for record */ 416787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write16(hal2, H2I_ADC_C1, (pbus->pbusnr << H2I_C1_DMA_SHIFT) 417787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer | (2 << H2I_C1_CLKID_SHIFT) 418787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer | (hal2->adc.voices << H2I_C1_DATAT_SHIFT)); 419787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 420787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 421787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_start_dac(struct snd_hal2 *hal2) 422787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 423787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_pbus *pbus = &hal2->dac.pbus; 424787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 425787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->pbus->pbdma_dptr = hal2->dac.desc_dma; 426787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT; 427787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* enable DAC */ 428787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECTX); 429787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 430787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 431787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_start_adc(struct snd_hal2 *hal2) 432787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 433787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_pbus *pbus = &hal2->adc.pbus; 434787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 435787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->pbus->pbdma_dptr = hal2->adc.desc_dma; 436787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pbus->pbus->pbdma_ctrl = pbus->ctrl | HPC3_PDMACTRL_ACT; 437787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* enable ADC */ 438787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_setbit16(hal2, H2I_DMA_PORT_EN, H2I_DMA_PORT_EN_CODECR); 439787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 440787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 441787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic inline void hal2_stop_dac(struct snd_hal2 *hal2) 442787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 443787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->dac.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; 444787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* The HAL2 itself may remain enabled safely */ 445787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 446787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 447787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic inline void hal2_stop_adc(struct snd_hal2 *hal2) 448787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 449787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->adc.pbus.pbus->pbdma_ctrl = HPC3_PDMACTRL_LD; 450787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 451787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 452787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_alloc_dmabuf(struct hal2_codec *codec) 453787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 454787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_desc *desc; 455787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_addr_t desc_dma, buffer_dma; 456787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int count = H2_BUF_SIZE / H2_BLOCK_SIZE; 457787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int i; 458787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 459787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE, 460787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &buffer_dma, GFP_KERNEL); 461787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (!codec->buffer) 462787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -ENOMEM; 463787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc), 464787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &desc_dma, GFP_KERNEL); 465787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (!desc) { 466787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_free_noncoherent(NULL, H2_BUF_SIZE, 467787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->buffer, buffer_dma); 468787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -ENOMEM; 469787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 470787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->buffer_dma = buffer_dma; 471787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->desc_dma = desc_dma; 472787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->desc = desc; 473787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer for (i = 0; i < count; i++) { 474787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer desc->desc.pbuf = buffer_dma + i * H2_BLOCK_SIZE; 475787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer desc->desc.cntinfo = HPCDMA_XIE | H2_BLOCK_SIZE; 476787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer desc->desc.pnext = (i == count - 1) ? 477787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer desc_dma : desc_dma + (i + 1) * sizeof(struct hal2_desc); 478787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer desc++; 479787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 480787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_cache_sync(NULL, codec->desc, count * sizeof(struct hal2_desc), 481787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer DMA_TO_DEVICE); 482787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->desc_count = count; 483787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 484787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 485787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 486787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_free_dmabuf(struct hal2_codec *codec) 487787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 488787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc), 489787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->desc, codec->desc_dma); 490787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer, 491787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->buffer_dma); 492787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 493787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 494787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct snd_pcm_hardware hal2_pcm_hw = { 495787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .info = (SNDRV_PCM_INFO_MMAP | 496787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer SNDRV_PCM_INFO_MMAP_VALID | 497787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer SNDRV_PCM_INFO_INTERLEAVED | 498787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer SNDRV_PCM_INFO_BLOCK_TRANSFER), 499787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .formats = SNDRV_PCM_FMTBIT_S16_BE, 500787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .rates = SNDRV_PCM_RATE_8000_48000, 501787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .rate_min = 8000, 502787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .rate_max = 48000, 503787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .channels_min = 2, 504787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .channels_max = 2, 505787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .buffer_bytes_max = 65536, 506787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .period_bytes_min = 1024, 507787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .period_bytes_max = 65536, 508787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .periods_min = 2, 509787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .periods_max = 1024, 510787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 511787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 512787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_pcm_hw_params(struct snd_pcm_substream *substream, 513787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_hw_params *params) 514787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 515787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 516787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 517787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 518787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) 519787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 520787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 521787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 522787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 523787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 524787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_pcm_hw_free(struct snd_pcm_substream *substream) 525787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 526787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return snd_pcm_lib_free_pages(substream); 527787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 528787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 529787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_playback_open(struct snd_pcm_substream *substream) 530787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 531787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_runtime *runtime = substream->runtime; 532787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 533787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 534787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 535787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer runtime->hw = hal2_pcm_hw; 536787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 537787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = hal2_alloc_dmabuf(&hal2->dac); 538787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err) 539787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 540787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 541787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 542787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 543787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_playback_close(struct snd_pcm_substream *substream) 544787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 545787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 546787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 547787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_free_dmabuf(&hal2->dac); 548787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 549787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 550787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 551787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_playback_prepare(struct snd_pcm_substream *substream) 552787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 553787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 554787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_runtime *runtime = substream->runtime; 555787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *dac = &hal2->dac; 556787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 557787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->voices = runtime->channels; 558787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->sample_rate = hal2_compute_rate(dac, runtime->rate); 559787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer memset(&dac->pcm_indirect, 0, sizeof(dac->pcm_indirect)); 560787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; 561787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 562787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->substream = substream; 563787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_setup_dac(hal2); 564787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 565787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 566787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 567787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_playback_trigger(struct snd_pcm_substream *substream, int cmd) 568787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 569787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 570787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 571787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer switch (cmd) { 572787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case SNDRV_PCM_TRIGGER_START: 573787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->dac.pcm_indirect.hw_io = hal2->dac.buffer_dma; 574787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->dac.pcm_indirect.hw_data = 0; 575787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer substream->ops->ack(substream); 576787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_start_dac(hal2); 577787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 578787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case SNDRV_PCM_TRIGGER_STOP: 579787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_stop_dac(hal2); 580787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 581787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer default: 582787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -EINVAL; 583787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 584787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 585787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 586787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 587787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic snd_pcm_uframes_t 588787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferhal2_playback_pointer(struct snd_pcm_substream *substream) 589787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 590787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 591787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *dac = &hal2->dac; 592787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 593787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return snd_pcm_indirect_playback_pointer(substream, &dac->pcm_indirect, 594787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->pbus.pbus->pbdma_bptr); 595787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 596787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 597787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_playback_transfer(struct snd_pcm_substream *substream, 598787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_indirect *rec, size_t bytes) 599787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 600787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 601787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned char *buf = hal2->dac.buffer + rec->hw_data; 602787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 603787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer memcpy(buf, substream->runtime->dma_area + rec->sw_data, bytes); 604787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_cache_sync(NULL, buf, bytes, DMA_TO_DEVICE); 605787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 606787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 607787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 608787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_playback_ack(struct snd_pcm_substream *substream) 609787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 610787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 611787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *dac = &hal2->dac; 612787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 613787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; 614787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_indirect_playback_transfer(substream, 615787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &dac->pcm_indirect, 616787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_playback_transfer); 617787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 618787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 619787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 620787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_capture_open(struct snd_pcm_substream *substream) 621787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 622787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_runtime *runtime = substream->runtime; 623787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 624787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *adc = &hal2->adc; 625787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 626787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 627787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer runtime->hw = hal2_pcm_hw; 628787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 629787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = hal2_alloc_dmabuf(adc); 630787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err) 631787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 632787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 633787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 634787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 635787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_capture_close(struct snd_pcm_substream *substream) 636787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 637787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 638787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 639787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_free_dmabuf(&hal2->adc); 640787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 641787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 642787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 643787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_capture_prepare(struct snd_pcm_substream *substream) 644787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 645787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 646787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_runtime *runtime = substream->runtime; 647787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *adc = &hal2->adc; 648787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 649787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->voices = runtime->channels; 650787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->sample_rate = hal2_compute_rate(adc, runtime->rate); 651787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer memset(&adc->pcm_indirect, 0, sizeof(adc->pcm_indirect)); 652787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->pcm_indirect.hw_buffer_size = H2_BUF_SIZE; 653787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; 654787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->pcm_indirect.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 655787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->substream = substream; 656787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_setup_adc(hal2); 657787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 658787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 659787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 660787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_capture_trigger(struct snd_pcm_substream *substream, int cmd) 661787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 662787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 663787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 664787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer switch (cmd) { 665787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case SNDRV_PCM_TRIGGER_START: 666787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->adc.pcm_indirect.hw_io = hal2->adc.buffer_dma; 667787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->adc.pcm_indirect.hw_data = 0; 668787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer printk(KERN_DEBUG "buffer_dma %x\n", hal2->adc.buffer_dma); 669787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_start_adc(hal2); 670787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 671787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer case SNDRV_PCM_TRIGGER_STOP: 672787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_stop_adc(hal2); 673787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer break; 674787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer default: 675787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -EINVAL; 676787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 677787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 678787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 679787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 680787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic snd_pcm_uframes_t 681787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferhal2_capture_pointer(struct snd_pcm_substream *substream) 682787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 683787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 684787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *adc = &hal2->adc; 685787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 686787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return snd_pcm_indirect_capture_pointer(substream, &adc->pcm_indirect, 687787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer adc->pbus.pbus->pbdma_bptr); 688787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 689787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 690787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_capture_transfer(struct snd_pcm_substream *substream, 691787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm_indirect *rec, size_t bytes) 692787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 693787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 694787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned char *buf = hal2->adc.buffer + rec->hw_data; 695787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 696787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer dma_cache_sync(NULL, buf, bytes, DMA_FROM_DEVICE); 697787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer memcpy(substream->runtime->dma_area + rec->sw_data, buf, bytes); 698787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 699787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 700787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_capture_ack(struct snd_pcm_substream *substream) 701787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 702787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); 703787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hal2_codec *adc = &hal2->adc; 704787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 705787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_indirect_capture_transfer(substream, 706787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &adc->pcm_indirect, 707787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_capture_transfer); 708787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 709787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 710787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 711787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct snd_pcm_ops hal2_playback_ops = { 712787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .open = hal2_playback_open, 713787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .close = hal2_playback_close, 714787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .ioctl = snd_pcm_lib_ioctl, 715787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .hw_params = hal2_pcm_hw_params, 716787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .hw_free = hal2_pcm_hw_free, 717787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .prepare = hal2_playback_prepare, 718787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .trigger = hal2_playback_trigger, 719787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .pointer = hal2_playback_pointer, 720787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .ack = hal2_playback_ack, 721787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 722787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 723787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct snd_pcm_ops hal2_capture_ops = { 724787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .open = hal2_capture_open, 725787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .close = hal2_capture_close, 726787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .ioctl = snd_pcm_lib_ioctl, 727787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .hw_params = hal2_pcm_hw_params, 728787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .hw_free = hal2_pcm_hw_free, 729787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .prepare = hal2_capture_prepare, 730787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .trigger = hal2_capture_trigger, 731787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .pointer = hal2_capture_pointer, 732787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .ack = hal2_capture_ack, 733787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 734787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 735787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int __devinit hal2_pcm_create(struct snd_hal2 *hal2) 736787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 737787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_pcm *pcm; 738787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 739787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 740787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* create first pcm device with one outputs and one input */ 741787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = snd_pcm_new(hal2->card, "SGI HAL2 Audio", 0, 1, 1, &pcm); 742787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) 743787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 744787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 745787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer pcm->private_data = hal2; 746787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer strcpy(pcm->name, "SGI HAL2"); 747787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 748787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* set operators */ 749787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 750787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &hal2_playback_ops); 751787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, 752787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &hal2_capture_ops); 753787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, 754787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_dma_continuous_data(GFP_KERNEL), 755787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 0, 1024 * 1024); 756787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 757787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 758787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 759787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 760787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_dev_free(struct snd_device *device) 761787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 762787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2 = device->device_data; 763787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 764787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer free_irq(SGI_HPCDMA_IRQ, hal2); 765787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer kfree(hal2); 766787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 767787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 768787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 769787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct snd_device_ops hal2_ops = { 770787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .dev_free = hal2_dev_free, 771787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 772787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 773787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void hal2_init_codec(struct hal2_codec *codec, struct hpc3_regs *hpc3, 774787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int index) 775787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 776787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->pbus.pbusnr = index; 777787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer codec->pbus.pbus = &hpc3->pbdma[index]; 778787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 779787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 780787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_detect(struct snd_hal2 *hal2) 781787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 782787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned short board, major, minor; 783787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer unsigned short rev; 784787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 785787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* reset HAL2 */ 786787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(0, &hal2->ctl_regs->isr); 787787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 788787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* release reset */ 789787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_write(H2_ISR_GLOBAL_RESET_N | H2_ISR_CODEC_RESET_N, 790787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer &hal2->ctl_regs->isr); 791787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 792787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 793787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_i_write16(hal2, H2I_RELAY_C, H2I_RELAY_C_STATE); 794787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer rev = hal2_read(&hal2->ctl_regs->rev); 795787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (rev & H2_REV_AUDIO_PRESENT) 796787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -ENODEV; 797787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 798787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer board = (rev & H2_REV_BOARD_M) >> 12; 799787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer major = (rev & H2_REV_MAJOR_CHIP_M) >> 4; 800787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer minor = (rev & H2_REV_MINOR_CHIP_M); 801787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 802787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer printk(KERN_INFO "SGI HAL2 revision %i.%i.%i\n", 803787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer board, major, minor); 804787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 805787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 806787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 807787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 808787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int hal2_create(struct snd_card *card, struct snd_hal2 **rchip) 809787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 810787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *hal2; 811787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct hpc3_regs *hpc3 = hpc3c0; 812787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 813787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 814787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2 = kzalloc(sizeof(struct snd_hal2), GFP_KERNEL); 815787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (!hal2) 816787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -ENOMEM; 817787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 818787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->card = card; 819787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 820787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, IRQF_SHARED, 821787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer "SGI HAL2", hal2)) { 822787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer printk(KERN_ERR "HAL2: Can't get irq %d\n", SGI_HPCDMA_IRQ); 823787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer kfree(hal2); 824787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -EAGAIN; 825787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 826787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 827787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->ctl_regs = (struct hal2_ctl_regs *)hpc3->pbus_extregs[0]; 828787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->aes_regs = (struct hal2_aes_regs *)hpc3->pbus_extregs[1]; 829787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->vol_regs = (struct hal2_vol_regs *)hpc3->pbus_extregs[2]; 830787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2->syn_regs = (struct hal2_syn_regs *)hpc3->pbus_extregs[3]; 831787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 832787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (hal2_detect(hal2) < 0) { 833787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer kfree(hal2); 834787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return -ENODEV; 835787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 836787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 837787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_init_codec(&hal2->dac, hpc3, 0); 838787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hal2_init_codec(&hal2->adc, hpc3, 1); 839787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 840787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* 841787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * All DMA channel interfaces in HAL2 are designed to operate with 842787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * PBUS programmed for 2 cycles in D3, 2 cycles in D4 and 2 cycles 843787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * in D5. HAL2 is a 16-bit device which can accept both big and little 844787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * endian format. It assumes that even address bytes are on high 845787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * portion of PBUS (15:8) and assumes that HPC3 is programmed to 846787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * accept a live (unsynchronized) version of P_DREQ_N from HAL2. 847787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer */ 848787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer#define HAL2_PBUS_DMACFG ((0 << HPC3_DMACFG_D3R_SHIFT) | \ 849787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (2 << HPC3_DMACFG_D4R_SHIFT) | \ 850787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (2 << HPC3_DMACFG_D5R_SHIFT) | \ 851787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (0 << HPC3_DMACFG_D3W_SHIFT) | \ 852787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (2 << HPC3_DMACFG_D4W_SHIFT) | \ 853787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (2 << HPC3_DMACFG_D5W_SHIFT) | \ 854787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer HPC3_DMACFG_DS16 | \ 855787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer HPC3_DMACFG_EVENHI | \ 856787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer HPC3_DMACFG_RTIME | \ 857787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer (8 << HPC3_DMACFG_BURST_SHIFT) | \ 858787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer HPC3_DMACFG_DRQLIVE) 859787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer /* 860787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * Ignore what's mentioned in the specification and write value which 861787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer * works in The Real World (TM) 862787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer */ 863787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hpc3->pbus_dmacfg[hal2->dac.pbus.pbusnr][0] = 0x8208844; 864787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer hpc3->pbus_dmacfg[hal2->adc.pbus.pbusnr][0] = 0x8208844; 865787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 866787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, hal2, &hal2_ops); 867787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) { 868787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer free_irq(SGI_HPCDMA_IRQ, hal2); 869787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer kfree(hal2); 870787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 871787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 872787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer *rchip = hal2; 873787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 874787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 875787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 876787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int __devinit hal2_probe(struct platform_device *pdev) 877787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 878787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_card *card; 879787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_hal2 *chip; 880787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer int err; 881787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 882bd7dd77c2a05c530684eea2e3af16449ae9c5d52Takashi Iwai err = snd_card_create(index, id, THIS_MODULE, 0, &card); 883bd7dd77c2a05c530684eea2e3af16449ae9c5d52Takashi Iwai if (err < 0) 884bd7dd77c2a05c530684eea2e3af16449ae9c5d52Takashi Iwai return err; 885787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 886787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = hal2_create(card, &chip); 887787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) { 888787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_card_free(card); 889787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 890787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 891787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_card_set_dev(card, &pdev->dev); 892787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 893787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = hal2_pcm_create(chip); 894787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) { 895787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_card_free(card); 896787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 897787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 898787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = hal2_mixer_create(chip); 899787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) { 900787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_card_free(card); 901787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 902787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 903787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 904787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer strcpy(card->driver, "SGI HAL2 Audio"); 905787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer strcpy(card->shortname, "SGI HAL2 Audio"); 906787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer sprintf(card->longname, "%s irq %i", 907787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer card->shortname, 908787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer SGI_HPCDMA_IRQ); 909787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 910787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer err = snd_card_register(card); 911787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer if (err < 0) { 912787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_card_free(card); 913787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return err; 914787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 915787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer platform_set_drvdata(pdev, card); 916787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 917787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 918787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 9192f229a31aac86ea6911d70ec4c79196ca711d625Takashi Iwaistatic int __devexit hal2_remove(struct platform_device *pdev) 920787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 921787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer struct snd_card *card = platform_get_drvdata(pdev); 922787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 923787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer snd_card_free(card); 924787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer platform_set_drvdata(pdev, NULL); 925787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return 0; 926787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 927787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 928787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic struct platform_driver hal2_driver = { 929787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .probe = hal2_probe, 930787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .remove = __devexit_p(hal2_remove), 931787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .driver = { 932787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .name = "sgihal2", 933787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer .owner = THIS_MODULE, 934787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer } 935787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer}; 936787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 937787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic int __init alsa_card_hal2_init(void) 938787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 939787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer return platform_driver_register(&hal2_driver); 940787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 941787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 942787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerferstatic void __exit alsa_card_hal2_exit(void) 943787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer{ 944787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer platform_driver_unregister(&hal2_driver); 945787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer} 946787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfer 947787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfermodule_init(alsa_card_hal2_init); 948787dba37a6ff5c80c67f37c081712a6e4af92e25Thomas Bogendoerfermodule_exit(alsa_card_hal2_exit); 949