blob: 74166327c7bb31c66ce11529980d51696cd917db [file] [log] [blame]
/*
*
* Marvell Orion Alsa Sound driver
*
* Author: Maen Suleiman
* Copyright (C) 2008 Marvell Ltd.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <sound/driver.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/asoundef.h>
#include <sound/asound.h>
#include "twsi/mvTwsi.h"
#include "audio/dac/mvCLAudioCodec.h"
#include "boardEnv/mvBoardEnvLib.h"
/*
* Initialize the audio decoder.
*/
int
cs42l51_init(void)
{
MV_AUDIO_CODEC_DEV codec_params;
unsigned char reg_data;
codec_params.ADCMode = MV_I2S_MODE;
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
codec_params.twsiSlave.moreThen256 = MV_FALSE;
codec_params.twsiSlave.validOffset = MV_TRUE;
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet();
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet();
if(mvCLAudioCodecInit(&codec_params) == MV_FALSE)
{
printk("Error - Cannot initialize audio decoder.at address =0x%x",
codec_params.twsiSlave.slaveAddr.address);
return -1;
}
/* Use the signal processor. */
mvCLAudioCodecRegSet(&codec_params,0x9,0x40);
/* Unmute PCM-A & PCM-B and set default */
mvCLAudioCodecRegSet(&codec_params,0x10,0x60);
mvCLAudioCodecRegSet(&codec_params,0x11,0x60);
/* default for AOUTx*/
mvCLAudioCodecRegSet(&codec_params,0x16,0x05);
mvCLAudioCodecRegSet(&codec_params,0x17,0x05);
/* swap channels */
mvCLAudioCodecRegSet(&codec_params,0x18,0xff);
if (0) {
int i;
for (i=1; i<= 0x21 ; i++) {
reg_data = mvCLAudioCodecRegGet(&codec_params,i);
printk("CLS reg=0x%02x val=0x%02x\n",i,reg_data);
}
}
return 0;
}
#define MVAUD_NUM_VOLUME_STEPS (40)
static MV_U8 auddec_volume_mapping[MVAUD_NUM_VOLUME_STEPS] =
{
0x19, 0xB2, 0xB7, 0xBD, 0xC3, 0xC9, 0xCF, 0xD5,
0xD8, 0xE1, 0xE7, 0xED, 0xF3, 0xF9, 0xFF, 0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
};
/*
* Get the audio decoder volume for both channels.
* 0 is lowest volume, MVAUD_NUM_VOLUME_STEPS-1 is the highest volume.
*/
void
cs42l51_vol_get(MV_U8 *vol_list)
{
MV_AUDIO_CODEC_DEV codec_params;
MV_U8 reg_data;
MV_U32 i;
MV_U32 vol_idx;
codec_params.ADCMode = MV_I2S_MODE;
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
codec_params.twsiSlave.moreThen256 = MV_FALSE;
codec_params.twsiSlave.validOffset = MV_TRUE;
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet();
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet();
for(vol_idx = 0; vol_idx < 2; vol_idx++)
{
reg_data = mvCLAudioCodecRegGet(&codec_params,0x16 + vol_idx);
/*printk("\tVolume was get: 0x%x.\n",
reg_data);*/
/* Look for the index that mapps to this dB value. */
for(i = 0; i < MVAUD_NUM_VOLUME_STEPS; i++)
{
if (reg_data == auddec_volume_mapping[i])
break;
if (( auddec_volume_mapping[i] > auddec_volume_mapping[MVAUD_NUM_VOLUME_STEPS-1])
&& (reg_data > auddec_volume_mapping[i])
&& (reg_data < auddec_volume_mapping[i+1]))
break;
}
vol_list[vol_idx] = i;
/*printk("\tvol_list[%d] = %d.\n",vol_idx,
vol_list[vol_idx]);*/
}
return;
}
/*
* Set the audio decoder volume for both channels.
* 0 is lowest volume, MVAUD_NUM_VOLUME_STEPS-1 is the highest volume.
*/
void
cs42l51_vol_set(MV_U8 *vol_list)
{
MV_AUDIO_CODEC_DEV codec_params;
MV_U32 vol_idx;
codec_params.ADCMode = MV_I2S_MODE;
codec_params.DACDigitalIFFormat = MV_I2S_UP_TO_24_BIT;
codec_params.twsiSlave.moreThen256 = MV_FALSE;
codec_params.twsiSlave.validOffset = MV_TRUE;
codec_params.twsiSlave.slaveAddr.address = mvBoardA2DTwsiAddrGet();
codec_params.twsiSlave.slaveAddr.type = mvBoardA2DTwsiAddrTypeGet();
for(vol_idx = 0; vol_idx < 2; vol_idx++)
{
/*printk("\tvol_list[%d] = %d.\n",vol_idx,
vol_list[vol_idx]);*/
if(vol_list[vol_idx] >= MVAUD_NUM_VOLUME_STEPS)
vol_list[vol_idx] = MVAUD_NUM_VOLUME_STEPS -1;
mvCLAudioCodecRegSet(&codec_params,0x16 + vol_idx,
auddec_volume_mapping[vol_list[vol_idx]]);
/*printk("\tVolume was set to 0x%x.\n",
auddec_volume_mapping[vol_list[vol_idx]]);*/
}
return;
}