3
* Marvell Orion Alsa Sound driver
5
* Author: Maen Suleiman
6
* Copyright (C) 2008 Marvell Ltd.
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
14
#include <linux/ioport.h>
15
#include <linux/interrupt.h>
16
#include <linux/platform_device.h>
17
#include <linux/init.h>
18
#include <linux/slab.h>
19
#include <linux/version.h>
20
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
21
#include <sound/driver.h>
23
#include <sound/core.h>
24
#include <sound/initval.h>
25
#include <sound/control.h>
26
#include <sound/pcm.h>
27
#include <sound/asoundef.h>
28
#include <sound/asound.h>
30
#include "twsi/mvTwsi.h"
31
#include "audio/dac/mvCLAudioCodec.h"
32
#include "boardEnv/mvBoardEnvLib.h"
37
* Initialize the audio decoder.
40
cs42l51_init(MV_U8 port)
42
MV_AUDIO_CODEC_DEV codec_params;
43
unsigned char reg_data;
45
codec_params.chanNum = mvBoardA2DTwsiChanNumGet(port);
46
codec_params.ADCMode = MV_I2S_MODE;
47
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
48
codec_params.twsiSlave.moreThen256 = MV_FALSE;
49
codec_params.twsiSlave.validOffset = MV_TRUE;
50
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet(port);
51
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet(port);
52
if(mvCLAudioCodecInit(&codec_params) == MV_FALSE)
54
printk("Error - Cannot initialize audio decoder.at address =0x%x",
55
codec_params.twsiSlave.slaveAddr.address);
59
#ifdef CONFIG_MACH_DOVE_RD_AVNG
61
mvCLAudioCodecRegSet(&codec_params,0x8,
62
mvCLAudioCodecRegGet(&codec_params,0x8)|0xE0);
65
/* Use the signal processor. */
66
mvCLAudioCodecRegSet(&codec_params,0x9,0x40);
68
/* Unmute PCM-A & PCM-B and set default */
69
mvCLAudioCodecRegSet(&codec_params,0x10,0x10);
70
mvCLAudioCodecRegSet(&codec_params,0x11,0x10);
72
/* default for AOUTx*/
73
mvCLAudioCodecRegSet(&codec_params,0x16,0x05);
74
mvCLAudioCodecRegSet(&codec_params,0x17,0x05);
77
mvCLAudioCodecRegSet(&codec_params,0x18,0xff);
80
for (i=1; i<= 0x21 ; i++) {
81
reg_data = mvCLAudioCodecRegGet(&codec_params,i);
82
printk("CLS reg=0x%02x val=0x%02x\n",i,reg_data);
90
#define MVAUD_NUM_VOLUME_STEPS (40)
91
static MV_U8 auddec_volume_mapping[MVAUD_NUM_VOLUME_STEPS] =
93
0x19, 0xB2, 0xB7, 0xBD, 0xC3, 0xC9, 0xCF, 0xD5,
94
0xD8, 0xE1, 0xE7, 0xED, 0xF3, 0xF9, 0xFF, 0x00,
95
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
96
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
97
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
102
* Get the audio decoder volume for both channels.
103
* 0 is lowest volume, MVAUD_NUM_VOLUME_STEPS-1 is the highest volume.
107
cs42l51_vol_get(MV_U8 port, MV_U8 *vol_list)
109
MV_AUDIO_CODEC_DEV codec_params;
114
codec_params.chanNum = mvBoardA2DTwsiChanNumGet(port);
115
codec_params.ADCMode = MV_I2S_MODE;
116
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
117
codec_params.twsiSlave.moreThen256 = MV_FALSE;
118
codec_params.twsiSlave.validOffset = MV_TRUE;
119
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet(port);
120
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet(port);
123
for(vol_idx = 0; vol_idx < 2; vol_idx++)
125
reg_data = mvCLAudioCodecRegGet(&codec_params,0x16 + vol_idx);
127
/*printk("\tVolume was get: 0x%x.\n",
130
/* Look for the index that mapps to this dB value. */
131
for(i = 0; i < MVAUD_NUM_VOLUME_STEPS; i++)
133
if (reg_data == auddec_volume_mapping[i])
135
if (( auddec_volume_mapping[i] > auddec_volume_mapping[MVAUD_NUM_VOLUME_STEPS-1])
136
&& (reg_data > auddec_volume_mapping[i])
137
&& (reg_data < auddec_volume_mapping[i+1]))
142
vol_list[vol_idx] = i;
143
/*printk("\tvol_list[%d] = %d.\n",vol_idx,
144
vol_list[vol_idx]);*/
153
* Set the audio decoder volume for both channels.
154
* 0 is lowest volume, MVAUD_NUM_VOLUME_STEPS-1 is the highest volume.
157
cs42l51_vol_set(MV_U8 port, MV_U8 *vol_list)
159
MV_AUDIO_CODEC_DEV codec_params;
162
codec_params.chanNum = mvBoardA2DTwsiChanNumGet(port);
163
codec_params.ADCMode = MV_I2S_MODE;
164
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
165
codec_params.twsiSlave.moreThen256 = MV_FALSE;
166
codec_params.twsiSlave.validOffset = MV_TRUE;
167
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet(port);
168
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet(port);
171
for(vol_idx = 0; vol_idx < 2; vol_idx++)
173
/*printk("\tvol_list[%d] = %d.\n",vol_idx,
174
vol_list[vol_idx]);*/
176
if(vol_list[vol_idx] >= MVAUD_NUM_VOLUME_STEPS)
177
vol_list[vol_idx] = MVAUD_NUM_VOLUME_STEPS -1;
179
mvCLAudioCodecRegSet(&codec_params,0x16 + vol_idx,
180
auddec_volume_mapping[vol_list[vol_idx]]);
182
/*printk("\tVolume was set to 0x%x.\n",
183
auddec_volume_mapping[vol_list[vol_idx]]);*/
189
#ifdef CONFIG_MACH_DOVE_RD_AVNG
192
#define internalMic 1
196
* Set the audio codec's ADC path.
199
cs42l51_input_select(MV_U8 port, int type)
201
MV_AUDIO_CODEC_DEV codec_params;
203
codec_params.chanNum = mvBoardA2DTwsiChanNumGet(port);
204
codec_params.ADCMode = MV_I2S_MODE;
205
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
206
codec_params.twsiSlave.moreThen256 = MV_FALSE;
207
codec_params.twsiSlave.validOffset = MV_TRUE;
208
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet(port);
209
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet(port);
211
if (type == internalMic) {
212
/* Set PDN bit first */
213
mvCLAudioCodecRegSet(&codec_params,0x02,0x01);
214
/* Wait until codec is in standby mode */
216
/* Enable PDN_PGAB and PDN_ADCB also */
217
mvCLAudioCodecRegSet(&codec_params,0x02,0x15);
218
/* Enable PDN_MICB and disable PDN_MICA and PDN_MICBIAS */
219
mvCLAudioCodecRegSet(&codec_params,0x03,0xA8);
220
/* MICBIAS_SEL set to AIN2B, disable MICB_BOOST and enable MICA_BOOST */
221
mvCLAudioCodecRegSet(&codec_params,0x05,0x11);
222
/* Set AIN3A->Pre Amp->PGAA and AIN1B->PGAB */
223
mvCLAudioCodecRegSet(&codec_params,0x07,0x30);
224
/* Disable PDN bit last */
225
mvCLAudioCodecRegSet(&codec_params,0x02,0x14);
226
} else if (type == phoneIn) {
227
/* Set PDN bit first */
228
mvCLAudioCodecRegSet(&codec_params,0x02,0x01);
229
/* Wait until codec is in standby mode */
231
/* Enable PDN_PGAA and PDN_ADCA also */
232
mvCLAudioCodecRegSet(&codec_params,0x02,0x0B);
233
/* Enable PDN_MICA and disable PDN_MICB and PDN_MICBIAS */
234
mvCLAudioCodecRegSet(&codec_params,0x03,0xA4);
235
/* MICBIAS_SEL set to AIN2B, disable MICA_BOOST and enable MICB_BOOST */
236
mvCLAudioCodecRegSet(&codec_params,0x05,0x12);
237
/* Set AIN3B->Pre Amp->PGAB and AIN1A->PGAA */
238
mvCLAudioCodecRegSet(&codec_params,0x07,0xC0);
239
/* Disable PDN bit last */
240
mvCLAudioCodecRegSet(&codec_params,0x02,0x0A);
242
/* default to LineIn */
243
/* Set PDN bit first */
244
mvCLAudioCodecRegSet(&codec_params,0x02,0x01);
245
/* Wait until codec is in standby mode */
247
/* Enable PDN_MICB, PDN_MICA, and PDN_MICBIAS */
248
mvCLAudioCodecRegSet(&codec_params,0x03,0xAE);
249
/* MICBIAS_SEL set to AIN3B, disable both MICB_BOOST and MICA_BOOST */
250
mvCLAudioCodecRegSet(&codec_params,0x05,0x0);
251
/* Set AIN1A->PGAA and AIN1B->PGAB */
252
mvCLAudioCodecRegSet(&codec_params,0x07,0x0);
253
/* Disable PDN bit last */
254
mvCLAudioCodecRegSet(&codec_params,0x02,0x0);
261
for (i=1; i<= 0x21 ; i++) {
262
reg_data = mvCLAudioCodecRegGet(&codec_params,i);
263
printk("CLS reg=0x%02x val=0x%02x\n",i,reg_data);