1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-28 20:58:06 +02:00

jz4740 asoc: Add new internel codec driver.

Add qi lb60 board support.
Remove unneeded files.
This commit is contained in:
Lars-Peter Clausen 2009-09-15 03:35:41 +02:00 committed by Xiangfu Liu
parent 299c9e29ef
commit 8bb63272c3
24 changed files with 725 additions and 4307 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,22 @@
/* /*
* Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
*
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/ */
#ifndef _ICODEC_H #ifndef _ICODEC_H
#define _ICODEC_H #define _ICODEC_H
/* jzcodec register space */
#define ICODEC_1_LOW 0x00 /* bit0 -- bit15 in CDCCR1 */
#define ICODEC_1_HIGH 0x01 /* bit16 -- bit31 in CDCCR1 */
#define ICODEC_2_LOW 0x02 /* bit0 -- bit16 in CDCCR2 */
#define ICODEC_2_HIGH 0x03 /* bit16 -- bit31 in CDCCR2 */
#define JZCODEC_CACHEREGNUM 4
#define JZCODEC_SYSCLK 0 #define JZCODEC_SYSCLK 0
extern struct snd_soc_dai jzcodec_dai; extern struct snd_soc_dai jz_codec_dai;
extern struct snd_soc_codec_device soc_codec_dev_jzcodec; extern struct snd_soc_codec_device soc_codec_dev_jzcodec;
#endif #endif

View File

@ -1,981 +0,0 @@
/*
* 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/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include "../jz4750/jz4750-pcm.h"
#include "jzdlv.h"
#define AUDIO_NAME "jzdlv"
#define JZDLV_VERSION "1.0"
/*
* Debug
*/
#define JZDLV_DEBUG 0
#ifdef JZDLV_DEBUG
#define dbg(format, arg...) \
printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
#else
#define dbg(format, arg...) do {} while (0)
#endif
#define err(format, arg...) \
printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
#define info(format, arg...) \
printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
#define warn(format, arg...) \
printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
struct snd_soc_codec_device soc_codec_dev_jzdlv;
/* codec private data */
struct jzdlv_priv {
unsigned int sysclk;
};
/*
* jzdlv register cache
*/
static u16 jzdlv_reg[JZDLV_CACHEREGNUM];
int read_codec_file(int addr)
{
while (__icdc_rgwr_ready());
__icdc_set_addr(addr);
mdelay(1);
return(__icdc_get_value());
}
static void printk_codec_files(void)
{
int cnt, val;
//printk("\n");
#if 0
printk("REG_CPM_I2SCDR=0x%08x\n",REG_CPM_I2SCDR);
printk("REG_CPM_CLKGR=0x%08x\n",REG_CPM_CLKGR);
printk("REG_CPM_CPCCR=0x%08x\n",REG_CPM_CPCCR);
printk("REG_AIC_FR=0x%08x\n",REG_AIC_FR);
printk("REG_AIC_CR=0x%08x\n",REG_AIC_CR);
printk("REG_AIC_I2SCR=0x%08x\n",REG_AIC_I2SCR);
printk("REG_AIC_SR=0x%08x\n",REG_AIC_SR);
printk("REG_ICDC_RGDATA=0x%08x\n",REG_ICDC_RGDATA);
#endif
for (cnt = 0; cnt < JZDLV_CACHEREGNUM ; cnt++) {
val = read_codec_file(cnt);
jzdlv_reg[cnt] = val;
//printk(" ( %d : 0x%x ) ",cnt ,jzdlv_reg[cnt]);
}
//printk("\n");
}
void write_codec_file(int addr, int val)
{
while (__icdc_rgwr_ready());
__icdc_set_addr(addr);
__icdc_set_cmd(val); /* write */
mdelay(1);
__icdc_set_rgwr();
mdelay(1);
//jzdlv_reg[addr] = val;
}
int write_codec_file_bit(int addr, int bitval, int mask_bit)
{
int val;
while (__icdc_rgwr_ready());
__icdc_set_addr(addr);
mdelay(1);
val = __icdc_get_value(); /* read */
val &= ~(1 << mask_bit);
if (bitval == 1)
val |= 1 << mask_bit;
#if 0
while (__icdc_rgwr_ready());
__icdc_set_addr(addr);
__icdc_set_cmd(val); /* write */
mdelay(1);
__icdc_set_rgwr();
mdelay(1);
#else
write_codec_file(addr, val);
#endif
while (__icdc_rgwr_ready());
__icdc_set_addr(addr);
val = __icdc_get_value(); /* read */
if (((val >> mask_bit) & bitval) == bitval)
return 1;
else
return 0;
}
/*
* read jzdlv register cache
*/
static inline unsigned int jzdlv_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
u16 *cache = codec->reg_cache;
if (reg >= JZDLV_CACHEREGNUM)
return -1;
return cache[reg];
}
static inline unsigned int jzdlv_read(struct snd_soc_codec *codec,
unsigned int reg)
{
u8 data;
data = reg;
if (codec->hw_write(codec->control_data, &data, 1) != 1)
return -EIO;
if (codec->hw_read(codec->control_data, &data, 1) != 1)
return -EIO;
return data;
}
/*
* write jzdlv register cache
*/
static inline void jzdlv_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, u16 value)
{
u16 *cache = codec->reg_cache;
if (reg >= JZDLV_CACHEREGNUM) {
return;
}
cache[reg] = value;
}
/*
* write to the jzdlv register space
*/
static int jzdlv_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
jzdlv_write_reg_cache(codec, reg, value);
if(codec->hw_write)
codec->hw_write(&value, NULL, reg);
return 0;
}
static const char *jzdlv_input_select[] = {"Line In", "Mic"};
static const char *jzdlv_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
static const struct soc_enum jzdlv_enum[] = {
SOC_ENUM_SINGLE(0x04, 2, 2, jzdlv_input_select),
SOC_ENUM_SINGLE(0x05, 1, 4, jzdlv_deemph),
};
/* set Audio data replay */
void set_audio_data_replay(void)
{
write_codec_file(9, 0xff);
write_codec_file(8, 0x20);// only CCMC
mdelay(10);
/* DAC path */
write_codec_file_bit(1, 0, 4);//CR1.HP_DIS->0
write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1
write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1
write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0
write_codec_file_bit(1, 1, 3);//CR1.DACSEL->1
write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0
mdelay(100);
write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0
write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0
write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1
mdelay(100);
write_codec_file_bit(1, 0, 5);//DAC_MUTE->0
}
/* unset Audio data replay */
void unset_audio_data_replay(void)
{
write_codec_file_bit(1, 1, 5);//DAC_MUTE->1
mdelay(200);
write_codec_file_bit(5, 1, 6);//SB_OUT->1
write_codec_file_bit(5, 1, 7);//SB_DAC->1
write_codec_file_bit(5, 1, 4);//SB_MIX->1
write_codec_file_bit(6, 1, 0);//SB_SLEEP->1
write_codec_file_bit(6, 1, 1);//SB->1
write_codec_file(9, 0xff);
write_codec_file(8, 0x3f);
}
/* set Record MIC input audio without playback */
static void set_record_mic_input_audio_without_playback(void)
{
/* ADC path for MIC IN */
write_codec_file_bit(1, 1, 2);
write_codec_file_bit(1, 0, 7);//CR1.SB_MICBIAS->0
//write_codec_file_bit(1, 1, 6);//CR1.MONO->1
write_codec_file(22, 0x40);//mic 1
write_codec_file_bit(23, 0, 7);//AGC1.AGC_EN->0
write_codec_file_bit(3, 1, 7);//CR1.HP_DIS->1
write_codec_file_bit(5, 1, 3);//PMR1.SB_LIN->1
write_codec_file_bit(5, 1, 0);//PMR1.SB_IND->1
write_codec_file_bit(1, 0, 2);//CR1.BYPASS->0
write_codec_file_bit(1, 0, 3);//CR1.DACSEL->0
write_codec_file_bit(6, 1, 3);// gain set
write_codec_file_bit(5, 0, 5);//PMR1.SB_MIX->0
mdelay(100);
write_codec_file_bit(5, 0, 6);//PMR1.SB_OUT->0
write_codec_file(1, 0x4);
}
/* unset Record MIC input audio without playback */
static void unset_record_mic_input_audio_without_playback(void)
{
/* ADC path for MIC IN */
write_codec_file_bit(5, 1, 4);//SB_ADC->1
write_codec_file_bit(1, 1, 7);//CR1.SB_MICBIAS->1
write_codec_file(22, 0xc0);//CR3.SB_MIC1
}
#if 0
static irqreturn_t aic_codec_irq(int irq, void *dev_id)
{
u8 file_9 = read_codec_file(9);
u8 file_8 = read_codec_file(8);
//printk("--- 8:0x%x 9:0x%x ---\n",file_8,file_9);
if ((file_9 & 0x1f) == 0x10) {
// have hp short circuit
write_codec_file(8, 0x3f);//mask all interrupt
write_codec_file_bit(5, 1, 6);//SB_OUT->1
mdelay(300);
while ((read_codec_file(9) & 0x4) != 0x4);
while ((read_codec_file(9) & 0x10) == 0x10) {
write_codec_file(9, 0x10);
}
write_codec_file_bit(5, 0, 6);//SB_OUT->0
mdelay(300);
while ((read_codec_file(9) & 0x8) != 0x8);
write_codec_file(9, file_9);
write_codec_file(8, file_8);
return IRQ_HANDLED;
}
if (file_9 & 0x8)
ramp_up_end = jiffies;
else if (file_9 & 0x4)
ramp_down_end = jiffies;
else if (file_9 & 0x2)
gain_up_end = jiffies;
else if (file_9 & 0x1)
gain_down_end = jiffies;
write_codec_file(9, file_9);
if (file_9 & 0xf)
wake_up(&pop_wait_queue);
while (REG_ICDC_RGDATA & 0x100);
return IRQ_HANDLED;
}
#else
static irqreturn_t aic_codec_irq(int irq, void *dev_id)
{
u8 file_9 = read_codec_file(9);
u8 file_8 = read_codec_file(8);
//printk("--- 1 8:0x%x 9:0x%x ---\n",file_8,file_9);
if ((file_9 & 0x1f) == 0x10) {
write_codec_file(8, 0x3f);
write_codec_file_bit(5, 1, 6);//SB_OUT->1
mdelay(300);
while ((read_codec_file(9) & 0x4) != 0x4);
while ((read_codec_file(9) & 0x10) == 0x10) {
write_codec_file(9, 0x10);
}
write_codec_file_bit(5, 0, 6);//SB_OUT->0
mdelay(300);
while ((read_codec_file(9) & 0x8) != 0x8);
write_codec_file(9, file_9);
write_codec_file(8, file_8);
return IRQ_HANDLED;
}
/*if (file_9 & 0x8)
ramp_up_end = jiffies;
else if (file_9 & 0x4)
ramp_down_end = jiffies;
else if (file_9 & 0x2)
gain_up_end = jiffies;
else if (file_9 & 0x1)
gain_down_end = jiffies;*/
write_codec_file(9, file_9);
/*if (file_9 & 0xf)
wake_up(&pop_wait_queue);*/
while (REG_ICDC_RGDATA & 0x100);
return IRQ_HANDLED;
}
#endif
static int jzdlv_reset(struct snd_soc_codec *codec)
{
/* reset DLV codec. from hibernate mode to sleep mode */
write_codec_file(0, 0xf);
write_codec_file_bit(6, 0, 0);
write_codec_file_bit(6, 0, 1);
mdelay(200);
//write_codec_file(0, 0xf);
write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0
write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0
mdelay(10);//wait for stability
return 0;
}
#if 0
static int jzdlv_sync(struct snd_soc_codec *codec)
{
u16 *cache = codec->reg_cache;
int i, r = 0;
for (i = 0; i < JZDLV_CACHEREGNUM; i++)
r |= jzdlv_write(codec, i, cache[i]);
return r;
};
#endif
static const struct snd_kcontrol_new jzdlv_snd_controls[] = {
//SOC_DOUBLE_R("Master Playback Volume", 1, 1, 0, 3, 0),
SOC_DOUBLE_R("Master Playback Volume", DLV_CGR8, DLV_CGR9, 0, 31, 0),
//SOC_DOUBLE_R("MICBG", ICODEC_2_LOW, ICODEC_2_LOW, 4, 3, 0),
//SOC_DOUBLE_R("Line", 2, 2, 0, 31, 0),
SOC_DOUBLE_R("Line", DLV_CGR10, DLV_CGR10, 0, 15, 0),
};
/* add non dapm controls */
static int jzdlv_add_controls(struct snd_soc_codec *codec)
{
int err, i;
for (i = 0; i < ARRAY_SIZE(jzdlv_snd_controls); i++) {
err = snd_ctl_add(codec->card,
snd_soc_cnew(&jzdlv_snd_controls[i], codec, NULL));
if (err < 0)
return err;
}
return 0;
}
/* Output Mixer */
static const struct snd_kcontrol_new jzdlv_output_mixer_controls[] = {
SOC_DAPM_SINGLE("Line Bypass Switch", 0x04, 3, 1, 0),
SOC_DAPM_SINGLE("Mic Sidetone Switch", 0x04, 5, 1, 0),
SOC_DAPM_SINGLE("HiFi Playback Switch", 0x04, 4, 1, 0),
};
/* Input mux */
static const struct snd_kcontrol_new jzdlv_input_mux_controls =
SOC_DAPM_ENUM("Input Select", jzdlv_enum[0]);
static const struct snd_soc_dapm_widget jzdlv_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("Output Mixer", 0x06, 4, 1,
&jzdlv_output_mixer_controls[0],
ARRAY_SIZE(jzdlv_output_mixer_controls)),
//SND_SOC_DAPM_DAC("DAC", "HiFi Playback", 0x06, 3, 1),
SND_SOC_DAPM_OUTPUT("LOUT"),
SND_SOC_DAPM_OUTPUT("LHPOUT"),
SND_SOC_DAPM_OUTPUT("ROUT"),
SND_SOC_DAPM_OUTPUT("RHPOUT"),
//SND_SOC_DAPM_ADC("ADC", "HiFi Capture", 0x06, 2, 1),
SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &jzdlv_input_mux_controls),
SND_SOC_DAPM_PGA("Line Input", 0x06, 0, 1, NULL, 0),
SND_SOC_DAPM_MICBIAS("Mic Bias", 0x06, 1, 1),
SND_SOC_DAPM_INPUT("MICIN"),
SND_SOC_DAPM_INPUT("RLINEIN"),
SND_SOC_DAPM_INPUT("LLINEIN"),
};
static const struct snd_soc_dapm_route intercon[] = {
/* output mixer */
{"Output Mixer", "Line Bypass Switch", "Line Input"},
{"Output Mixer", "HiFi Playback Switch", "DAC"},
{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
/* outputs */
{"RHPOUT", NULL, "Output Mixer"},
{"ROUT", NULL, "Output Mixer"},
{"LHPOUT", NULL, "Output Mixer"},
{"LOUT", NULL, "Output Mixer"},
/* input mux */
{"Input Mux", "Line In", "Line Input"},
{"Input Mux", "Mic", "Mic Bias"},
{"ADC", NULL, "Input Mux"},
/* inputs */
{"Line Input", NULL, "LLINEIN"},
{"Line Input", NULL, "RLINEIN"},
{"Mic Bias", NULL, "MICIN"},
};
static void init_codec(void)
{
/* reset DLV codec. from hibernate mode to sleep mode */
write_codec_file(0, 0xf);
write_codec_file_bit(6, 0, 0);
write_codec_file_bit(6, 0, 1);
mdelay(200);
//write_codec_file(0, 0xf);
write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0
write_codec_file_bit(5, 0, 4);//PMR1.SB_ADC->0
mdelay(10);//wait for stability
}
static int jzdlv_add_widgets(struct snd_soc_codec *codec)
{
snd_soc_dapm_new_controls(codec, jzdlv_dapm_widgets,
ARRAY_SIZE(jzdlv_dapm_widgets));
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
snd_soc_dapm_new_widgets(codec);
return 0;
}
static int jzdlv_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
int speed = 0;
int val = 0;
/* sample channel */
switch (params_channels(params)) {
case 1:
write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono
break;
case 2:
write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo
break;
}
/* sample rate */
switch (params_rate(params)) {
case 8000:
speed = 10;
break;
case 9600:
speed = 9;
break;
case 11025:
speed = 8;
break;
case 12000:
speed = 7;
break;
case 16000:
speed = 6;
break;
case 22050:
speed = 5;
break;
case 24000:
speed = 4;
break;
case 32000:
speed = 3;
break;
case 44100:
speed = 2;
break;
case 48000:
speed = 1;
break;
case 96000:
speed = 0;
break;
default:
printk(" invalid rate :0x%08x\n",params_rate(params));
}
val = (speed << 4) | speed;
jzdlv_write(codec, DLV_CCR2, val);
return 0;
}
static int jzdlv_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
//struct snd_soc_pcm_runtime *rtd = substream->private_data;
//struct snd_soc_device *socdev = rtd->socdev;
//struct snd_soc_codec *codec = socdev->codec;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
//case SNDRV_PCM_TRIGGER_RESUME:
//case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
init_codec();
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
REG_AIC_I2SCR = 0x10;
mdelay(1);
set_audio_data_replay();
mdelay(5);
write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0
__aic_flush_fifo();
} else {
set_record_mic_input_audio_without_playback();
mdelay(10);
REG_AIC_I2SCR = 0x10;
mdelay(20);
__aic_flush_fifo();
write_codec_file_bit(5, 1, 7);
}
break;
case SNDRV_PCM_TRIGGER_STOP:
//case SNDRV_PCM_TRIGGER_SUSPEND:
//case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
unset_audio_data_replay();
} else {
unset_record_mic_input_audio_without_playback();
}
break;
default:
ret = -EINVAL;
}
return ret;
}
static int jzdlv_pcm_prepare(struct snd_pcm_substream *substream)
{
/*struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec; */
return 0;
}
static void jzdlv_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
/* deactivate */
if (!codec->active) {
udelay(50);
}
}
static int jzdlv_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
u16 reg_val = jzdlv_read_reg_cache(codec, 2/*DLV_1_LOW*/);
if (mute != 0)
mute = 1;
if (mute)
reg_val = reg_val | (0x1 << 14);
else
reg_val = reg_val & ~(0x1 << 14);
//jzdlv_write(codec, DLV_1_LOW, reg_val);
return 0;
}
static int jzdlv_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
struct jzdlv_priv *jzdlv = codec->private_data;
jzdlv->sysclk = freq;
return 0;
}
/*
* Set's ADC and Voice DAC format. called by apus_hw_params() in apus.c
*/
static int jzdlv_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
/* struct snd_soc_codec *codec = codec_dai->codec; */
/* set master/slave audio interface. codec side */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
/* set master mode for codec */
break;
case SND_SOC_DAIFMT_CBS_CFS:
/* set slave mode for codec */
break;
default:
return -EINVAL;
}
/* interface format . set some parameter for codec side */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
/* set I2S mode for codec */
break;
case SND_SOC_DAIFMT_RIGHT_J:
/* set right J mode */
break;
case SND_SOC_DAIFMT_LEFT_J:
/* set left J mode */
break;
case SND_SOC_DAIFMT_DSP_A:
/* set dsp A mode */
break;
case SND_SOC_DAIFMT_DSP_B:
/* set dsp B mode */
break;
default:
return -EINVAL;
}
/* clock inversion. codec side */
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_IB_IF:
break;
case SND_SOC_DAIFMT_IB_NF:
break;
case SND_SOC_DAIFMT_NB_IF:
break;
default:
return -EINVAL;
}
/* jzcodec_write(codec, 0, val); */
return 0;
}
static int jzdlv_dapm_event(struct snd_soc_codec *codec, int event)
{
/* u16 reg_val; */
switch (event) {
case SNDRV_CTL_POWER_D0: /* full On */
/* vref/mid, osc on, dac unmute */
/* u16 reg_val = jzcodec_read_reg_cache(codec, ICODEC_1_LOW); */
/* jzcodec_write(codec, 0, val); */
break;
case SNDRV_CTL_POWER_D1: /* partial On */
case SNDRV_CTL_POWER_D2: /* partial On */
break;
case SNDRV_CTL_POWER_D3hot: /* Off, with power */
/* everything off except vref/vmid, */
/*reg_val = 0x0800;
jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val);
reg_val = 0x0017;
jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val);
REG_ICDC_CDCCR1 = jzcodec_reg[0];
mdelay(2);
reg_val = 0x2102;
jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val);
reg_val = 0x001f;
jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val);
REG_ICDC_CDCCR1 = jzcodec_reg[0];
mdelay(2);
reg_val = 0x3302;
jzcodec_write_reg_cache(codec, ICODEC_1_LOW, reg_val);
reg_val = 0x0003;
jzcodec_write_reg_cache(codec, ICODEC_1_HIGH, reg_val);
REG_ICDC_CDCCR1 = jzcodec_reg[0];*/
break;
case SNDRV_CTL_POWER_D3cold: /* Off, without power */
/* everything off, dac mute, inactive */
/*reg_val = 0x2302;
jzcodec_write(codec, ICODEC_1_LOW, reg_val);
reg_val = 0x001b;
jzcodec_write(codec, ICODEC_1_HIGH, reg_val);
mdelay(1);
reg_val = 0x2102;
jzcodec_write(codec, ICODEC_1_LOW, reg_val);
reg_val = 0x001b;
jzcodec_write(codec, ICODEC_1_HIGH, reg_val);*/
break;
}
//codec->dapm_state = event;
return 0;
}
#define JZDLV_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_12000 |\
SNDRV_PCM_RATE_24000)
#define JZDLV_FORMATS (SNDRV_PCM_FORMAT_S8 | SNDRV_PCM_FMTBIT_S16_LE)
struct snd_soc_dai jzdlv_dai = {
.name = "JZDLV",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
.channels_max = 2,
.rates = JZDLV_RATES,
.formats = JZDLV_FORMATS,},
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = JZDLV_RATES,
.formats = JZDLV_FORMATS,},
.ops = {
.trigger = jzdlv_pcm_trigger,
.prepare = jzdlv_pcm_prepare,
.hw_params = jzdlv_hw_params,
.shutdown = jzdlv_shutdown,
},
.dai_ops = {
.digital_mute = jzdlv_mute,
.set_sysclk = jzdlv_set_dai_sysclk,
.set_fmt = jzdlv_set_dai_fmt,
}
};
EXPORT_SYMBOL_GPL(jzdlv_dai);
#ifdef CONFIG_PM
static int jzdlv_suspend(struct platform_device *pdev, pm_message_t state)
{
#if 0
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->codec;
jzcodec_reg_pm[ICODEC_1_LOW] = jzcodec_read_reg_cache(codec, ICODEC_1_LOW);
jzcodec_reg_pm[ICODEC_1_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_1_HIGH);
jzcodec_reg_pm[ICODEC_2_LOW] = jzcodec_read_reg_cache(codec, ICODEC_2_LOW);
jzcodec_reg_pm[ICODEC_2_HIGH] = jzcodec_read_reg_cache(codec, ICODEC_2_HIGH);
jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
#endif
return 0;
}
static int jzdlv_resume(struct platform_device *pdev)
{
#if 0
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->codec;
u16 reg_val;
jzcodec_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
reg_val = jzcodec_reg_pm[ICODEC_1_LOW];
jzcodec_write(codec, ICODEC_1_LOW, reg_val);
reg_val = jzcodec_reg_pm[ICODEC_1_HIGH];
jzcodec_write(codec, ICODEC_1_HIGH, reg_val);
reg_val = jzcodec_reg_pm[ICODEC_2_LOW];
jzcodec_write(codec, ICODEC_2_LOW, reg_val);
reg_val = jzcodec_reg_pm[ICODEC_2_HIGH];
jzcodec_write(codec, ICODEC_2_HIGH, reg_val);
jzcodec_dapm_event(codec, codec->suspend_dapm_state);
#endif
return 0;
}
#else
#define jzdlv_suspend NULL
#define jzdlv_resume NULL
#endif
/*
* initialise the JZDLV driver
* register the mixer and dsp interfaces with the kernel
*/
static int jzdlv_init(struct snd_soc_device *socdev)
{
struct snd_soc_codec *codec = socdev->codec;
int ret = 0, retval;
/*REG_CPM_CPCCR &= ~(1 << 31);
REG_CPM_CPCCR &= ~(1 << 30);*/
write_codec_file(0, 0xf);
REG_AIC_I2SCR = 0x10;
__i2s_internal_codec();
__i2s_as_slave();
__i2s_select_i2s();
__aic_select_i2s();
__aic_reset();
mdelay(10);
REG_AIC_I2SCR = 0x10;
mdelay(20);
/* power on DLV */
write_codec_file(8, 0x3f);
write_codec_file(9, 0xff);
mdelay(10);
__cpm_start_idct();
__cpm_start_db();
__cpm_start_me();
__cpm_start_mc();
__cpm_start_ipu();
codec->name = "JZDLV";
codec->owner = THIS_MODULE;
codec->read = jzdlv_read_reg_cache;
codec->write = jzdlv_write;
//codec->dapm_event = jzdlv_dapm_event;
codec->dai = &jzdlv_dai;
codec->num_dai = 1;
codec->reg_cache_size = sizeof(jzdlv_reg);
codec->reg_cache = kmemdup(jzdlv_reg, sizeof(jzdlv_reg), GFP_KERNEL);
if (codec->reg_cache == NULL)
return -ENOMEM;
jzdlv_reset(codec);
/* register pcms */
ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
if (ret < 0) {
printk(KERN_ERR "jzdlv: failed to create pcms\n");
goto pcm_err;
}
/* power on device */
jzdlv_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
jzdlv_add_controls(codec);
jzdlv_add_widgets(codec);
ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "jzcodec: failed to register card\n");
goto card_err;
}
mdelay(10);
REG_AIC_I2SCR = 0x10;
mdelay(20);
/* power on DLV */
write_codec_file(9, 0xff);
write_codec_file(8, 0x3f);
retval = request_irq(IRQ_AIC, aic_codec_irq, IRQF_DISABLED, "aic_codec_irq", NULL);
if (retval) {
printk("Could not get aic codec irq %d\n", IRQ_AIC);
return retval;
}
printk_codec_files();
return ret;
card_err:
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
pcm_err:
kfree(codec->reg_cache);
return ret;
}
static struct snd_soc_device *jzdlv_socdev;
static int write_codec_reg(u16 * add, char * name, int reg)
{
write_codec_file(reg, *add);
return 0;
}
static int jzdlv_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
struct jzdlv_priv *jzdlv;
int ret = 0;
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
if (codec == NULL)
return -ENOMEM;
jzdlv = kzalloc(sizeof(struct jzdlv_priv), GFP_KERNEL);
if (jzdlv == NULL) {
kfree(codec);
return -ENOMEM;
}
codec->private_data = jzdlv;
socdev->codec = codec;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
jzdlv_socdev = socdev;
/* Add other interfaces here ,no I2C connection */
codec->hw_write = (hw_write_t)write_codec_reg;
//codec->hw_read = (hw_read_t)read_codec_reg;
ret = jzdlv_init(jzdlv_socdev);
if (ret < 0) {
codec = jzdlv_socdev->codec;
err("failed to initialise jzdlv\n");
kfree(codec);
}
return ret;
}
/* power down chip */
static int jzdlv_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->codec;
if (codec->control_data)
jzdlv_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
kfree(codec->private_data);
kfree(codec);
return 0;
}
struct snd_soc_codec_device soc_codec_dev_jzdlv = {
.probe = jzdlv_probe,
.remove = jzdlv_remove,
.suspend = jzdlv_suspend,
.resume = jzdlv_resume,
};
EXPORT_SYMBOL_GPL(soc_codec_dev_jzdlv);
MODULE_DESCRIPTION("ASoC JZDLV driver");
MODULE_AUTHOR("Richard");
MODULE_LICENSE("GPL");

View File

@ -1,50 +0,0 @@
/*
* 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.
*/
#ifndef _DLV_H
#define _DLV_H
/* jzdlv register space */
#define DLV_AICR 0x00
#define DLV_CR1 0x01
#define DLV_CR2 0x02
#define DLV_CCR1 0x03
#define DLV_CCR2 0x04
#define DLV_PMR1 0x05
#define DLV_PMR2 0x06
#define DLV_CRR 0x07
#define DLV_ICR 0x08
#define DLV_IFR 0x09
#define DLV_CGR1 0x0a
#define DLV_CGR2 0x0b
#define DLV_CGR3 0x0c
#define DLV_CGR4 0x0d
#define DLV_CGR5 0x0e
#define DLV_CGR6 0x0f
#define DLV_CGR7 0x10
#define DLV_CGR8 0x11
#define DLV_CGR9 0x12
#define DLV_CGR10 0x13
#define DLV_TR1 0x14
#define DLV_TR2 0x15
#define DLV_CR3 0x16
#define DLV_AGC1 0x17
#define DLV_AGC2 0x18
#define DLV_AGC3 0x19
#define DLV_AGC4 0x1a
#define DLV_AGC5 0x1b
#define JZDLV_CACHEREGNUM (DLV_AGC5+1)
#define JZDLV_SYSCLK 0
int read_codec_file(int addr);
int write_codec_file_bit(int addr, int bitval, int mask_bit);
void write_codec_file(int addr, int val);
extern struct snd_soc_dai jzdlv_dai;
extern struct snd_soc_codec_device soc_codec_dev_jzdlv;
#endif

View File

@ -1,34 +1,21 @@
config SND_JZ4740_SOC config SND_JZ4740_SOC
tristate "SoC Audio for Ingenic jz4740 chip" tristate "SoC Audio for Ingenic JZ4740 SoC"
depends on (JZ4740_PAVO || JZ4725_DIPPER || JZ4720_VIRGO) && SND_SOC depends on SOC_JZ4740 && SND_SOC
help help
Say Y or M if you want to add support for codecs attached to Say Y or M if you want to add support for codecs attached to
the Jz4740 AC97, I2S or SSP interface. You will also need the Jz4740 AC97, I2S or SSP interface. You will also need
to select the audio interfaces to support below. to select the audio interfaces to support below.
config SND_JZ4740_SOC_PAVO config SND_JZ4740_SOC_QI_LB60
tristate "SoC Audio support for Ingenic Jz4740 PAVO board" tristate "SoC Audio support for Qi Hardware Ben Nanonote"
depends on SND_JZ4740_SOC depends on SND_JZ4740_SOC && JZ4740_QI_LB60
select SND_JZ4740_SOC_I2S
select SND_SOC_JZCODEC
help help
Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 PAVO board. Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 QI_LB60 board.
config SND_JZ4740_AC97
tristate "select AC97 protocol and AC97 codec pcm core support"
depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO
select SND_AC97_CODEC
help
Say Y if you want to add AC97 protocol support for pcm core.
config SND_JZ4740_SOC_AC97
tristate "SoC Audio (AC97 protocol) for Ingenic jz4740 chip"
depends on SND_JZ4740_SOC && SND_JZ4740_AC97 && SND_JZ4740_SOC_PAVO
select AC97_BUS
select SND_SOC_AC97_BUS
help
Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4740 PAVO board.
config SND_JZ4740_SOC_I2S config SND_JZ4740_SOC_I2S
depends on SND_JZ4740_SOC && SND_JZ4740_SOC_PAVO depends on SND_JZ4740_SOC
tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip" tristate "SoC Audio (I2S protocol) for Ingenic jz4740 chip"
help help
Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 PAVO board. Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4740 QI_LB60 board.

View File

@ -2,14 +2,12 @@
# Jz4740 Platform Support # Jz4740 Platform Support
# #
snd-soc-jz4740-objs := jz4740-pcm.o snd-soc-jz4740-objs := jz4740-pcm.o
snd-soc-jz4740-ac97-objs := jz4740-ac97.o
snd-soc-jz4740-i2s-objs := jz4740-i2s.o snd-soc-jz4740-i2s-objs := jz4740-i2s.o
obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o obj-$(CONFIG_SND_JZ4740_SOC) += snd-soc-jz4740.o
obj-$(CONFIG_SND_JZ4740_SOC_AC97) += snd-soc-jz4740-ac97.o
obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
# Jz4740 Machine Support # Jz4740 Machine Support
snd-soc-pavo-objs := pavo.o snd-soc-qi-lb60-objs := qi_lb60.o
obj-$(CONFIG_SND_JZ4740_SOC_PAVO) += snd-soc-pavo.o obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o

View File

@ -1,261 +0,0 @@
/*
* linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip.
*
* Author: Richard
* Created: Dec 02, 2007
* Copyright: Ingenic Semiconductor Inc.
*
* 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/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <asm/irq.h>
#include <linux/mutex.h>
#include <asm/hardware.h>
#include <asm/arch/audio.h>
#include "jz4740-pcm.h"
#include "jz4740-ac97.h"
static DEFINE_MUTEX(car_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
static volatile long gsr_bits;
static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
unsigned short val = -1;
volatile u32 *reg_addr;
mutex_lock(&car_mutex);
out: mutex_unlock(&car_mutex);
return val;
}
static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
unsigned short val)
{
volatile u32 *reg_addr;
mutex_lock(&car_mutex);
mutex_unlock(&car_mutex);
}
static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97)
{
gsr_bits = 0;
}
static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97)
{
}
static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id)
{
long status;
return IRQ_NONE;
}
struct snd_ac97_bus_ops soc_ac97_ops = {
.read = jz4740_ac97_read,
.write = jz4740_ac97_write,
.warm_reset = jz4740_ac97_warm_reset,
.reset = jz4740_ac97_cold_reset,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = {
.name = "AC97 PCM Stereo out",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRTXPCDR,
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
DCMD_BURST32 | DCMD_WIDTH4,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = {
.name = "AC97 PCM Stereo in",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRRXPCDR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST32 | DCMD_WIDTH4,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = {
.name = "AC97 Aux PCM (Slot 5) Mono out",
.dev_addr = __PREG(MODR),
.drcmr = &DRCMRTXMODR,
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
DCMD_BURST16 | DCMD_WIDTH2,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = {
.name = "AC97 Aux PCM (Slot 5) Mono in",
.dev_addr = __PREG(MODR),
.drcmr = &DRCMRRXMODR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST16 | DCMD_WIDTH2,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = {
.name = "AC97 Mic PCM (Slot 6) Mono in",
.dev_addr = __PREG(MCDR),
.drcmr = &DRCMRRXMCDR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST16 | DCMD_WIDTH2,
};
#ifdef CONFIG_PM
static int jz4740_ac97_suspend(struct platform_device *pdev,
struct snd_soc_cpu_dai *dai)
{
return 0;
}
static int jz4740_ac97_resume(struct platform_device *pdev,
struct snd_soc_cpu_dai *dai)
{
return 0;
}
#else
#define jz4740_ac97_suspend NULL
#define jz4740_ac97_resume NULL
#endif
static int jz4740_ac97_probe(struct platform_device *pdev)
{
int ret;
return 0;
}
static void jz4740_ac97_remove(struct platform_device *pdev)
{
}
static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out;
else
cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in;
return 0;
}
static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out;
else
cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in;
return 0;
}
static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return -ENODEV;
else
cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in;
return 0;
}
#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
struct snd_soc_cpu_dai jz4740_ac97_dai[] = {
{
.name = "jz4740-ac97",
.id = 0,
.type = SND_SOC_DAI_AC97,
.probe = jz4740_ac97_probe,
.remove = jz4740_ac97_remove,
.suspend = jz4740_ac97_suspend,
.resume = jz4740_ac97_resume,
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 2,
.channels_max = 2,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {
.stream_name = "AC97 Capture",
.channels_min = 2,
.channels_max = 2,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = jz4740_ac97_hw_params,},
},
{
.name = "jz4740-ac97-aux",
.id = 1,
.type = SND_SOC_DAI_AC97,
.playback = {
.stream_name = "AC97 Aux Playback",
.channels_min = 1,
.channels_max = 1,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {
.stream_name = "AC97 Aux Capture",
.channels_min = 1,
.channels_max = 1,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = jz4740_ac97_hw_aux_params,},
},
{
.name = "jz4740-ac97-mic",
.id = 2,
.type = SND_SOC_DAI_AC97,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
.channels_max = 1,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = jz4740_ac97_hw_mic_params,},
},
};
EXPORT_SYMBOL_GPL(jz4740_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
MODULE_AUTHOR("Richard");
MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip");
MODULE_LICENSE("GPL");

View File

@ -1,21 +0,0 @@
/*
* linux/sound/soc/jz4740/jz4740-ac97.h
*
* 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.
*/
#ifndef _JZ4740_AC97_H
#define _JZ4740_AC97_H
#define JZ4740_DAI_AC97_HIFI 0
#define JZ4740_DAI_AC97_AUX 1
#define JZ4740_DAI_AC97_MIC 2
extern struct snd_soc_cpu_dai jz4740_ac97_dai[3];
/* platform data */
extern struct snd_ac97_bus_ops jz4740_ac97_ops;
#endif

View File

@ -4,13 +4,14 @@
* Free Software Foundation; either version 2 of the License, or (at your * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * option) any later version.
* *
* Jiejing Zhang(kzjeef(at)gmail.com) 2009: Make jz soc sound card
* loaded by soc-core.
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <sound/driver.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@ -42,7 +43,7 @@ static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_in = {
.dma_size = 2, .dma_size = 2,
}; };
static int jz4740_i2s_startup(struct snd_pcm_substream *substream) static int jz4740_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{ {
/*struct snd_soc_pcm_runtime *rtd = substream->private_data; /*struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/ struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/
@ -124,23 +125,22 @@ static void jz4740_snd_rx_ctrl(int on)
} }
static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params) struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
//struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int channels = params_channels(params); /* int channels = params_channels(params); */
jz4740_snd_rx_ctrl(0); jz4740_snd_rx_ctrl(0);
jz4740_snd_rx_ctrl(0); jz4740_snd_rx_ctrl(0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
//cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out; cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out;
rtd->dai->cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out; /*if (channels == 1)
if (channels == 1)
__aic_enable_mono2stereo(); __aic_enable_mono2stereo();
else else
__aic_disable_mono2stereo(); __aic_disable_mono2stereo();*/
} else } else
rtd->dai->cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_in; cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_in;
switch (params_format(params)) { switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8: case SNDRV_PCM_FORMAT_S8:
@ -162,7 +162,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
return 0; return 0;
} }
static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd) static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
{ {
int ret = 0; int ret = 0;
switch (cmd) { switch (cmd) {
@ -189,7 +189,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
return ret; return ret;
} }
static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream) static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{ {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
} else { } else {
@ -198,7 +198,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream)
return; return;
} }
static int jz4740_i2s_probe(struct platform_device *pdev) static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai)
{ {
__i2s_internal_codec(); __i2s_internal_codec();
__i2s_as_slave(); __i2s_as_slave();
@ -232,8 +232,7 @@ static int jz4740_i2s_probe(struct platform_device *pdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int jz4740_i2s_suspend(struct platform_device *dev, static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
if (!dai->active) if (!dai->active)
return 0; return 0;
@ -241,8 +240,7 @@ static int jz4740_i2s_suspend(struct platform_device *dev,
return 0; return 0;
} }
static int jz4740_i2s_resume(struct platform_device *pdev, static int jz4740_i2s_resume(struct snd_soc_dai *dai)
struct snd_soc_dai *dai)
{ {
if (!dai->active) if (!dai->active)
return 0; return 0;
@ -256,15 +254,22 @@ static int jz4740_i2s_resume(struct platform_device *pdev,
#endif #endif
#define JZ4740_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ #define JZ4740_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000) SNDRV_PCM_RATE_48000)
struct snd_soc_dai_ops snd_jz4740_i2s_dai_ops = {
.startup = jz4740_i2s_startup,
.shutdown = jz4740_i2s_shutdown,
.trigger = jz4740_i2s_trigger,
.hw_params = jz4740_i2s_hw_params,
.set_fmt = jz4740_i2s_set_dai_fmt,
.set_sysclk = jz4740_i2s_set_dai_sysclk,
};
struct snd_soc_dai jz4740_i2s_dai = { struct snd_soc_dai jz4740_i2s_dai = {
.name = "jz4740-i2s", .name = "jz4740-i2s",
.id = 0, .id = 0,
.type = SND_SOC_DAI_I2S,
.probe = jz4740_i2s_probe, .probe = jz4740_i2s_probe,
.suspend = jz4740_i2s_suspend, .suspend = jz4740_i2s_suspend,
.resume = jz4740_i2s_resume, .resume = jz4740_i2s_resume,
@ -272,25 +277,32 @@ struct snd_soc_dai jz4740_i2s_dai = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = JZ4740_I2S_RATES, .rates = JZ4740_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = { .capture = {
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 2,
.rates = JZ4740_I2S_RATES, .rates = JZ4740_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
.ops = {
.startup = jz4740_i2s_startup,
.shutdown = jz4740_i2s_shutdown,
.trigger = jz4740_i2s_trigger,
.hw_params = jz4740_i2s_hw_params,},
.dai_ops = {
.set_fmt = jz4740_i2s_set_dai_fmt,
.set_sysclk = jz4740_i2s_set_dai_sysclk,
}, },
.ops = &snd_jz4740_i2s_dai_ops,
}; };
EXPORT_SYMBOL_GPL(jz4740_i2s_dai); EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
static int __init jz4740_i2s_init(void)
{
return snd_soc_register_dai(&jz4740_i2s_dai);
}
static void __exit jz4740_i2s_exit(void)
{
snd_soc_unregister_dai(&jz4740_i2s_dai);
}
module_init(jz4740_i2s_init);
module_exit(jz4740_i2s_exit);
/* Module information */ /* Module information */
MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn"); MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn");
MODULE_DESCRIPTION("jz4740 I2S SoC Interface"); MODULE_DESCRIPTION("jz4740 I2S SoC Interface");

View File

View File

@ -12,7 +12,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <sound/driver.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
#include <sound/pcm_params.h> #include <sound/pcm_params.h>
@ -29,6 +28,29 @@ static int tran_bit = 0;
static int hw_params_cnt = 0; static int hw_params_cnt = 0;
#endif #endif
static struct jz4740_dma_client jz4740_dma_client_out = {
.name = "I2S PCM Stereo out"
};
static struct jz4740_dma_client jz4740_dma_client_in = {
.name = "I2S PCM Stereo in"
};
static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_out = {
.client = &jz4740_dma_client_out,
.channel = DMA_ID_AIC_TX,
.dma_addr = AIC_DR,
.dma_size = 2,
};
static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_in = {
.client = &jz4740_dma_client_in,
.channel = DMA_ID_AIC_RX,
.dma_addr = AIC_DR,
.dma_size = 2,
};
struct jz4740_dma_buf_aic { struct jz4740_dma_buf_aic {
struct jz4740_dma_buf_aic *next; struct jz4740_dma_buf_aic *next;
int size; /* buffer size in bytes */ int size; /* buffer size in bytes */
@ -66,13 +88,11 @@ static const struct snd_pcm_hardware jz4740_pcm_hardware = {
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER, SNDRV_PCM_INFO_BLOCK_TRANSFER,
.formats = SNDRV_PCM_FMTBIT_S16_LE | .formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_U8 |
SNDRV_PCM_FMTBIT_S8, SNDRV_PCM_FMTBIT_S8,
.rates = SNDRV_PCM_RATE_8000_48000/*0x3fe*/, .rates = SNDRV_PCM_RATE_8000_48000/*0x3fe*/,
.rate_min = 8000, .rate_min = 8000,
.rate_min = 48000, .rate_min = 48000,
.channels_min = 1,//2 .channels_min = 2,
.channels_max = 2, .channels_max = 2,
.buffer_bytes_max = 128 * 1024,//16 * 1024 .buffer_bytes_max = 128 * 1024,//16 * 1024
.period_bytes_min = PAGE_SIZE, .period_bytes_min = PAGE_SIZE,
@ -126,7 +146,7 @@ void audio_start_dma(struct jz4740_runtime_data *prtd, int mode)
unsigned long flags; unsigned long flags;
struct jz4740_dma_buf_aic *aic_buf; struct jz4740_dma_buf_aic *aic_buf;
int channel; int channel;
printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__);
switch (mode) { switch (mode) {
case DMA_MODE_WRITE: case DMA_MODE_WRITE:
/* free cur aic_buf */ /* free cur aic_buf */
@ -146,13 +166,11 @@ void audio_start_dma(struct jz4740_runtime_data *prtd, int mode)
aic_buf = prtd->next; aic_buf = prtd->next;
channel = prtd->params->channel; channel = prtd->params->channel;
if (aic_buf) { if (aic_buf) {
flags = claim_dma_lock();
disable_dma(channel); disable_dma(channel);
jz_set_alsa_dma(channel, mode, tran_bit); jz_set_alsa_dma(channel, mode, tran_bit);
set_dma_addr(channel, aic_buf->data); set_dma_addr(channel, aic_buf->data);
set_dma_count(channel, aic_buf->size); set_dma_count(channel, aic_buf->size);
enable_dma(channel); enable_dma(channel);
release_dma_lock(flags);
prtd->aic_dma_flag |= AIC_START_DMA; prtd->aic_dma_flag |= AIC_START_DMA;
} else { } else {
printk("next buffer is NULL for playback\n"); printk("next buffer is NULL for playback\n");
@ -179,13 +197,11 @@ void audio_start_dma(struct jz4740_runtime_data *prtd, int mode)
channel = prtd->params->channel; channel = prtd->params->channel;
if (aic_buf) { if (aic_buf) {
flags = claim_dma_lock();
disable_dma(channel); disable_dma(channel);
jz_set_alsa_dma(channel, mode, tran_bit); jz_set_alsa_dma(channel, mode, tran_bit);
set_dma_addr(channel, aic_buf->data); set_dma_addr(channel, aic_buf->data);
set_dma_count(channel, aic_buf->size); set_dma_count(channel, aic_buf->size);
enable_dma(channel); enable_dma(channel);
release_dma_lock(flags);
prtd->aic_dma_flag |= AIC_START_DMA; prtd->aic_dma_flag |= AIC_START_DMA;
} else { } else {
printk("next buffer is NULL for capture\n"); printk("next buffer is NULL for capture\n");
@ -283,16 +299,9 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4740_runtime_data *prtd = runtime->private_data; struct jz4740_runtime_data *prtd = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct jz4740_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; struct jz4740_pcm_dma_params *dma = &jz4740_i2s_pcm_stereo_out;
size_t totbytes = params_buffer_bytes(params); size_t totbytes = params_buffer_bytes(params);
int ret; int ret;
#ifdef CONFIG_SND_OSSEMUL
if (hw_params_cnt)
return 0;
else
hw_params_cnt++ ;
#endif
if (!dma) if (!dma)
return 0; return 0;
@ -343,7 +352,6 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
__dmac_disable_descriptor(prtd->params->channel); __dmac_disable_descriptor(prtd->params->channel);
__dmac_channel_disable_irq(prtd->params->channel); __dmac_channel_disable_irq(prtd->params->channel);
spin_unlock_irq(&prtd->lock); spin_unlock_irq(&prtd->lock);
return ret; return ret;
} }
@ -565,32 +573,8 @@ static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
unsigned long start; unsigned long start;
unsigned long off; unsigned long off;
u32 len; u32 len;
int ret = -ENXIO; printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
return 0;
off = vma->vm_pgoff << PAGE_SHIFT;
start = runtime->dma_addr;
len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes);
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len) {
return -EINVAL;
}
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
vma->vm_flags |= VM_IO;
#if defined(CONFIG_MIPS32)
pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
/* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */
#endif
ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
return ret;
} }
struct snd_pcm_ops jz4740_pcm_ops = { struct snd_pcm_ops jz4740_pcm_ops = {
@ -645,17 +629,19 @@ static void jz4740_pcm_free_dma_buffers(struct snd_pcm *pcm)
} }
} }
static u64 jz4740_pcm_dmamask = DMA_32BIT_MASK; static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
struct snd_pcm *pcm) struct snd_pcm *pcm)
{ {
int ret = 0; int ret = 0;
printk("pcm new\n");
if (!card->dev->dma_mask) if (!card->dev->dma_mask)
card->dev->dma_mask = &jz4740_pcm_dmamask; card->dev->dma_mask = &jz4740_pcm_dmamask;
if (!card->dev->coherent_dma_mask) if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_32BIT_MASK; card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
if (dai->playback.channels_min) { if (dai->playback.channels_min) {
ret = jz4740_pcm_preallocate_dma_buffer(pcm, ret = jz4740_pcm_preallocate_dma_buffer(pcm,
@ -684,6 +670,18 @@ struct snd_soc_platform jz4740_soc_platform = {
EXPORT_SYMBOL_GPL(jz4740_soc_platform); EXPORT_SYMBOL_GPL(jz4740_soc_platform);
static int __init jz4740_soc_platform_init(void)
{
return snd_soc_register_platform(&jz4740_soc_platform);
}
module_init(jz4740_soc_platform_init);
static void __exit jz4740_soc_platform_exit(void)
{
snd_soc_unregister_platform(&jz4740_soc_platform);
}
module_exit(jz4740_soc_platform_exit);
MODULE_AUTHOR("Richard"); MODULE_AUTHOR("Richard");
MODULE_DESCRIPTION("Ingenic Jz4740 PCM DMA module"); MODULE_DESCRIPTION("Ingenic Jz4740 PCM DMA module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

View File

@ -1,364 +0,0 @@
/*
* pavo.c -- SoC audio for PAVO
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include "../codecs/jzcodec.h"
#include "jz4740-pcm.h"
#include "jz4740-i2s.h"
#define PAVO_HP 0
#define PAVO_MIC 1
#define PAVO_LINE 2
#define PAVO_HEADSET 3
#define PAVO_HP_OFF 4
#define PAVO_SPK_ON 0
#define PAVO_SPK_OFF 1
/* audio clock in Hz - rounded from 12.235MHz */
#define PAVO_AUDIO_CLOCK 12288000
static int pavo_jack_func;
static int pavo_spk_func;
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit = 0;
return gpio_bit;
}
unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit = 0;
return gpio_bit;
}
static void pavo_ext_control(struct snd_soc_codec *codec)
{
int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
/* set up jack connection */
switch (pavo_jack_func) {
case PAVO_HP:
hp = 1;
/* set = unmute headphone */
//set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
//set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
break;
case PAVO_MIC:
mic = 1;
/* reset = mute headphone */
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
break;
case PAVO_LINE:
line = 1;
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
break;
case PAVO_HEADSET:
hs = 1;
mic = 1;
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
//set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
break;
}
if (pavo_spk_func == PAVO_SPK_ON)
spk = 1;
#if 0
/* set the enpoints to their new connetion states */
snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic);
snd_soc_dapm_set_endpoint(codec, "Line Jack", line);
snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
/* signal a DAPM event */
snd_soc_dapm_sync_endpoints(codec);
#endif
}
static int pavo_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;
/* check the jack status at stream startup */
pavo_ext_control(codec);
return 0;
}
/* we need to unmute the HP at shutdown as the mute burns power on pavo */
static void pavo_shutdown(struct snd_pcm_substream *substream)
{
/*struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;*/
return;
}
static int pavo_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int ret = 0;
/* set codec DAI configuration */
ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
if (ret < 0)
return ret;
/* set the codec system clock for DAC and ADC */
ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZCODEC_SYSCLK, 111,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
/* set the I2S system clock as input (unused) */
ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4740_I2S_SYSCLK, 0,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops pavo_ops = {
.startup = pavo_startup,
.hw_params = pavo_hw_params,
.shutdown = pavo_shutdown,
};
static int pavo_get_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = pavo_jack_func;
return 0;
}
static int pavo_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
if (pavo_jack_func == ucontrol->value.integer.value[0])
return 0;
pavo_jack_func = ucontrol->value.integer.value[0];
pavo_ext_control(codec);
return 1;
}
static int pavo_get_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = pavo_spk_func;
return 0;
}
static int pavo_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
if (pavo_spk_func == ucontrol->value.integer.value[0])
return 0;
pavo_spk_func = ucontrol->value.integer.value[0];
pavo_ext_control(codec);
return 1;
}
static int pavo_amp_event(struct snd_soc_dapm_widget *w, int event)
{
if (SND_SOC_DAPM_EVENT_ON(event))
//set_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON);
;
else
//reset_scoop_gpio(&corgiscoop_device.dev, PAVO_SCP_APM_ON);
;
return 0;
}
static int pavo_mic_event(struct snd_soc_dapm_widget *w, int event)
{
if (SND_SOC_DAPM_EVENT_ON(event))
//set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
;
else
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
;
return 0;
}
/* pavo machine dapm widgets */
static const struct snd_soc_dapm_widget jzcodec_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Mic Jack",pavo_mic_event),
SND_SOC_DAPM_SPK("Ext Spk", pavo_amp_event),
SND_SOC_DAPM_LINE("Line Jack", NULL),
SND_SOC_DAPM_HP("Headset Jack", NULL),
};
/* pavo machine audio map (connections to the codec pins) */
static const char *audio_map[][3] = {
/* headset Jack - in = micin, out = LHPOUT*/
{"Headset Jack", NULL, "LHPOUT"},
/* headphone connected to LHPOUT1, RHPOUT1 */
{"Headphone Jack", NULL, "LHPOUT"},
{"Headphone Jack", NULL, "RHPOUT"},
/* speaker connected to LOUT, ROUT */
{"Ext Spk", NULL, "ROUT"},
{"Ext Spk", NULL, "LOUT"},
/* mic is connected to MICIN (via right channel of headphone jack) */
{"MICIN", NULL, "Mic Jack"},
/* Same as the above but no mic bias for line signals */
{"MICIN", NULL, "Line Jack"},
{NULL, NULL, NULL},
};
static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
"Off"};
static const char *spk_function[] = {"On", "Off"};
static const struct soc_enum pavo_enum[] = {
SOC_ENUM_SINGLE_EXT(5, jack_function),
SOC_ENUM_SINGLE_EXT(2, spk_function),
};
static const struct snd_kcontrol_new jzcodec_pavo_controls[] = {
SOC_ENUM_EXT("Jack Function", pavo_enum[0], pavo_get_jack,
pavo_set_jack),
SOC_ENUM_EXT("Speaker Function", pavo_enum[1], pavo_get_spk,
pavo_set_spk),
};
/*
* Pavo for a jzcodec as connected on jz4740 Device
*/
static int pavo_jzcodec_init(struct snd_soc_codec *codec)
{
int i, err;
#if 0
snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
#endif
/* Add pavo specific controls */
for (i = 0; i < ARRAY_SIZE(jzcodec_pavo_controls); i++) {
err = snd_ctl_add(codec->card,
snd_soc_cnew(&jzcodec_pavo_controls[i],codec, NULL));
if (err < 0)
return err;
}
/* Add pavo specific widgets */
for(i = 0; i < ARRAY_SIZE(jzcodec_dapm_widgets); i++) {
snd_soc_dapm_new_control(codec, &jzcodec_dapm_widgets[i]);
}
#if 0
/* Set up pavo specific audio path audio_map */
for(i = 0; audio_map[i][0] != NULL; i++) {
snd_soc_dapm_connect_input(codec, audio_map[i][0],
audio_map[i][1], audio_map[i][2]);
}
snd_soc_dapm_sync_endpoints(codec);
#endif
return 0;
}
/* pavo digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link pavo_dai = {
.name = "JZCODEC",
.stream_name = "JZCODEC",
.cpu_dai = &jz4740_i2s_dai,
.codec_dai = &jzcodec_dai,
.init = pavo_jzcodec_init,
.ops = &pavo_ops,
};
/* pavo audio machine driver */
static struct snd_soc_machine snd_soc_machine_pavo = {
.name = "Pavo",
.dai_link = &pavo_dai,
.num_links = 1,
};
/* pavo audio subsystem */
static struct snd_soc_device pavo_snd_devdata = {
.machine = &snd_soc_machine_pavo,
.platform = &jz4740_soc_platform,
.codec_dev = &soc_codec_dev_jzcodec,
//.codec_data
};
static struct platform_device *pavo_snd_device;
static int __init pavo_init(void)
{
int ret;
pavo_snd_device = platform_device_alloc("soc-audio", -1);
if (!pavo_snd_device)
return -ENOMEM;
platform_set_drvdata(pavo_snd_device, &pavo_snd_devdata);
pavo_snd_devdata.dev = &pavo_snd_device->dev;
ret = platform_device_add(pavo_snd_device);
if (ret)
platform_device_put(pavo_snd_device);
return ret;
}
static void __exit pavo_exit(void)
{
platform_device_unregister(pavo_snd_device);
}
module_init(pavo_init);
module_exit(pavo_exit);
/* Module information */
MODULE_AUTHOR("Richard");
MODULE_DESCRIPTION("ALSA SoC Pavo");
MODULE_LICENSE("GPL");

View File

@ -1,34 +0,0 @@
config SND_JZ4750_SOC
tristate "SoC Audio for Ingenic jz4750 chip"
depends on (JZ4750_APUS || JZ4750_FUWA || JZ4750D_CETUS) && SND_SOC
help
Say Y or M if you want to add support for codecs attached to
the Jz4750 AC97, I2S or SSP interface. You will also need
to select the audio interfaces to support below.
config SND_JZ4750_SOC_APUS
tristate "SoC Audio support for Ingenic Jz4750 APUS board"
depends on SND_JZ4750_SOC
help
Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4750 APUS board.
config SND_JZ4750_AC97
tristate "select AC97 protocol and AC97 codec pcm core support"
depends on SND_JZ4750_SOC && SND_JZ4750_SOC_APUS
select SND_AC97_CODEC
help
Say Y if you want to add AC97 protocol support for pcm core.
config SND_JZ4750_SOC_AC97
tristate "SoC Audio (AC97 protocol) for Ingenic jz4750 chip"
depends on SND_JZ4750_SOC && SND_JZ4750_AC97 && SND_JZ4750_SOC_APUS
select AC97_BUS
select SND_SOC_AC97_BUS
help
Say Y if you want to use AC97 protocol and ac97 codec on Ingenic Jz4750 APUS board.
config SND_JZ4750_SOC_I2S
depends on SND_JZ4750_SOC && SND_JZ4750_SOC_APUS
tristate "SoC Audio (I2S protocol) for Ingenic jz4750 chip"
help
Say Y if you want to use I2S protocol and I2S codec on Ingenic Jz4750 APUS board.

View File

@ -1,15 +0,0 @@
#
# Jz4750 Platform Support
#
snd-soc-jz4750-objs := jz4750-pcm.o
snd-soc-jz4750-ac97-objs := jz4750-ac97.o
snd-soc-jz4750-i2s-objs := jz4750-i2s.o
obj-$(CONFIG_SND_JZ4750_SOC) += snd-soc-jz4750.o
obj-$(CONFIG_SND_JZ4750_SOC_AC97) += snd-soc-jz4750-ac97.o
obj-$(CONFIG_SND_JZ4750_SOC_I2S) += snd-soc-jz4750-i2s.o
# Jz4750 Machine Support
snd-soc-apus-objs := apus.o
obj-$(CONFIG_SND_JZ4750_SOC_APUS) += snd-soc-apus.o

View File

@ -1,405 +0,0 @@
/*
* apus.c -- SoC audio for APUS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "../codecs/jzdlv.h"
#include "jz4750-pcm.h"
#include "jz4750-i2s.h"
//static struct snd_soc_machine apus;
#define APUS_HP 0
#define APUS_MIC 1
#define APUS_LINE 2
#define APUS_HEADSET 3
#define APUS_HP_OFF 4
#define APUS_SPK_ON 0
#define APUS_SPK_OFF 1
static int apus_jack_func;
static int apus_spk_func;
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit = 0;
return gpio_bit;
}
unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit = 0;
return gpio_bit;
}
static void apus_ext_control(struct snd_soc_codec *codec)
{
int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
/* set up jack connection */
switch (apus_jack_func) {
case APUS_HP:
hp = 1;
snd_soc_dapm_disable_pin(codec, "Mic Jack");
snd_soc_dapm_disable_pin(codec, "Line Jack");
snd_soc_dapm_enable_pin(codec, "Headphone Jack");
snd_soc_dapm_disable_pin(codec, "Headset Jack");
break;
case APUS_MIC:
mic = 1;
snd_soc_dapm_enable_pin(codec, "Mic Jack");
snd_soc_dapm_disable_pin(codec, "Line Jack");
snd_soc_dapm_disable_pin(codec, "Headphone Jack");
snd_soc_dapm_disable_pin(codec, "Headset Jack");
break;
case APUS_LINE:
line = 1;
snd_soc_dapm_disable_pin(codec, "Mic Jack");
snd_soc_dapm_enable_pin(codec, "Line Jack");
snd_soc_dapm_disable_pin(codec, "Headphone Jack");
snd_soc_dapm_disable_pin(codec, "Headset Jack");
break;
case APUS_HEADSET:
hs = 1;
mic = 1;
snd_soc_dapm_enable_pin(codec, "Mic Jack");
snd_soc_dapm_disable_pin(codec, "Line Jack");
snd_soc_dapm_disable_pin(codec, "Headphone Jack");
snd_soc_dapm_enable_pin(codec, "Headset Jack");
break;
}
if (apus_spk_func == APUS_SPK_ON)
spk = 1;
if (apus_spk_func == APUS_SPK_ON)
snd_soc_dapm_enable_pin(codec, "Ext Spk");
else
snd_soc_dapm_disable_pin(codec, "Ext Spk");
/* signal a DAPM event */
snd_soc_dapm_sync(codec);
}
static int apus_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;
/* check the jack status at stream startup */
apus_ext_control(codec);
return 0;
}
/* we need to unmute the HP at shutdown as the mute burns power on apus */
static int apus_shutdown(struct snd_pcm_substream *substream)
{
/*struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;*/
return 0;
}
static int apus_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
int ret = 0;
/* set codec DAI configuration */
/*ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);*/
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
/*ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);*/
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
if (ret < 0)
return ret;
/* set the codec system clock for DAC and ADC */
/*ret = codec_dai->dai_ops.set_sysclk(codec_dai, JZDLV_SYSCLK, 111,
SND_SOC_CLOCK_IN);*/
ret = snd_soc_dai_set_sysclk(codec_dai, JZDLV_SYSCLK, 111,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
/* set the I2S system clock as input (unused) */
/*ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, JZ4750_I2S_SYSCLK, 0,
SND_SOC_CLOCK_IN);*/
ret = snd_soc_dai_set_sysclk(cpu_dai, JZ4750_I2S_SYSCLK, 0,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops apus_ops = {
.startup = apus_startup,
.hw_params = apus_hw_params,
.shutdown = apus_shutdown,
};
static int apus_get_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = apus_jack_func;
return 0;
}
static int apus_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
if (apus_jack_func == ucontrol->value.integer.value[0])
return 0;
apus_jack_func = ucontrol->value.integer.value[0];
apus_ext_control(codec);
return 1;
}
static int apus_get_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = apus_spk_func;
return 0;
}
static int apus_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
if (apus_spk_func == ucontrol->value.integer.value[0])
return 0;
apus_spk_func = ucontrol->value.integer.value[0];
apus_ext_control(codec);
return 1;
}
static int apus_amp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
{
if (SND_SOC_DAPM_EVENT_ON(event))
//set_scoop_gpio(&corgiscoop_device.dev, APUS_SCP_APM_ON);
;
else
//reset_scoop_gpio(&corgiscoop_device.dev, APUS_SCP_APM_ON);
;
return 0;
}
static int apus_mic_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event)
{
if (SND_SOC_DAPM_EVENT_ON(event))
//set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
;
else
//reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
;
return 0;
}
static int jzdlv_get_reg(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
//int reg = kcontrol->private_value & 0xFF;
//int shift = (kcontrol->private_value >> 8) & 0x0F;
//int mask = (kcontrol->private_value >> 16) & 0xFF;
//ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
return 0;
}
static int jzdlv_set_reg(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
//int reg = kcontrol->private_value & 0xFF;
//int shift = (kcontrol->private_value >> 8) & 0x0F;
//int mask = (kcontrol->private_value >> 16) & 0xFF;
/*if (((lm4857_regs[reg] >> shift) & mask) ==
ucontrol->value.integer.value[0])
return 0;
lm4857_regs[reg] &= ~(mask << shift);
lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
lm4857_write_regs();*/
return 1;
}
/* apus machine dapm widgets */
static const struct snd_soc_dapm_widget jzdlv_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Mic Jack",apus_mic_event),
SND_SOC_DAPM_SPK("Ext Spk", apus_amp_event),
SND_SOC_DAPM_LINE("Line Jack", NULL),
SND_SOC_DAPM_HP("Headset Jack", NULL),
};
/* apus machine audio map (connections to the codec pins) */
static const struct snd_soc_dapm_route audio_map[] = {
/* headset Jack - in = micin, out = LHPOUT*/
{"Headset Jack", NULL, "LHPOUT"},
/* headphone connected to LHPOUT1, RHPOUT1 */
{"Headphone Jack", NULL, "LHPOUT"},
{"Headphone Jack", NULL, "RHPOUT"},
/* speaker connected to LOUT, ROUT */
{"Ext Spk", NULL, "ROUT"},
{"Ext Spk", NULL, "LOUT"},
/* mic is connected to MICIN (via right channel of headphone jack) */
{"MICIN", NULL, "Mic Jack"},
/* Same as the above but no mic bias for line signals */
{"MICIN", NULL, "Line Jack"},
};
static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
"Off"};
static const char *spk_function[] = {"On", "Off"};
static const struct soc_enum apus_enum[] = {
SOC_ENUM_SINGLE_EXT(5, jack_function),
SOC_ENUM_SINGLE_EXT(2, spk_function),
};
static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
//static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
static const struct snd_kcontrol_new jzdlv_apus_controls[] = {
/* SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", 1, 0, 31, 0,
jzdlv_get_reg, jzdlv_set_reg, stereo_tlv),*/
SOC_SINGLE_EXT_TLV("PCM", 1, 0, 31, 0,
jzdlv_get_reg, jzdlv_set_reg, stereo_tlv),
SOC_SINGLE_EXT_TLV("Capture", 2, 0, 31, 0,
jzdlv_get_reg, jzdlv_set_reg, stereo_tlv),
/* SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
lm4857_get_reg, lm4857_set_reg, mono_tlv),*/
SOC_ENUM_EXT("Jack Function", apus_enum[0], apus_get_jack,apus_set_jack),
SOC_ENUM_EXT("Speaker Function", apus_enum[1], apus_get_spk,apus_set_spk),
};
/*
* Apus for a jzdlv as connected on jz4750 Device
*/
static int apus_jzdlv_init(struct snd_soc_codec *codec)
{
int i, err;
snd_soc_dapm_disable_pin(codec, "LLINEIN");
snd_soc_dapm_disable_pin(codec, "RLINEIN");
/* Add apus specific controls */
for (i = 0; i < ARRAY_SIZE(jzdlv_apus_controls); i++) {
err = snd_ctl_add(codec->card,
snd_soc_cnew(&jzdlv_apus_controls[i],codec, NULL));
if (err < 0)
return err;
}
/* Add apus specific widgets */
snd_soc_dapm_new_controls(codec, jzdlv_dapm_widgets,
ARRAY_SIZE(jzdlv_dapm_widgets));
/* Set up apus specific audio path audio_map */
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
snd_soc_dapm_sync(codec);
return 0;
}
/* apus digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link apus_dai = {
.name = "JZDLV",
.stream_name = "JZDLV",
.cpu_dai = &jz4750_i2s_dai,
.codec_dai = &jzdlv_dai,
.init = apus_jzdlv_init,
.ops = &apus_ops,
};
/* apus audio machine driver */
static struct snd_soc_machine snd_soc_machine_apus = {
.name = "Apus",
.dai_link = &apus_dai,
.num_links = 1,
};
/* apus audio subsystem */
static struct snd_soc_device apus_snd_devdata = {
.machine = &snd_soc_machine_apus,
.platform = &jz4750_soc_platform,
.codec_dev = &soc_codec_dev_jzdlv,
//.codec_data
};
static struct platform_device *apus_snd_device;
static int __init apus_init(void)
{
int ret;
apus_snd_device = platform_device_alloc("soc-audio", -1);
if (!apus_snd_device)
return -ENOMEM;
platform_set_drvdata(apus_snd_device, &apus_snd_devdata);
apus_snd_devdata.dev = &apus_snd_device->dev;
ret = platform_device_add(apus_snd_device);
if (ret)
platform_device_put(apus_snd_device);
return ret;
}
static void __exit apus_exit(void)
{
platform_device_unregister(apus_snd_device);
}
module_init(apus_init);
module_exit(apus_exit);
/* Module information */
MODULE_AUTHOR("Richard");
MODULE_DESCRIPTION("ALSA SoC Apus");
MODULE_LICENSE("GPL");

View File

@ -1,261 +0,0 @@
/*
* linux/sound/jz4740-ac97.c -- AC97 support for the Ingenic jz4740 chip.
*
* Author: Richard
* Created: Dec 02, 2007
* Copyright: Ingenic Semiconductor Inc.
*
* 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/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <asm/irq.h>
#include <linux/mutex.h>
#include <asm/hardware.h>
#include <asm/arch/audio.h>
#include "jz4740-pcm.h"
#include "jz4740-ac97.h"
static DEFINE_MUTEX(car_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
static volatile long gsr_bits;
static unsigned short jz4740_ac97_read(struct snd_ac97 *ac97,
unsigned short reg)
{
unsigned short val = -1;
volatile u32 *reg_addr;
mutex_lock(&car_mutex);
out: mutex_unlock(&car_mutex);
return val;
}
static void jz4740_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
unsigned short val)
{
volatile u32 *reg_addr;
mutex_lock(&car_mutex);
mutex_unlock(&car_mutex);
}
static void jz4740_ac97_warm_reset(struct snd_ac97 *ac97)
{
gsr_bits = 0;
}
static void jz4740_ac97_cold_reset(struct snd_ac97 *ac97)
{
}
static irqreturn_t jz4740_ac97_irq(int irq, void *dev_id)
{
long status;
return IRQ_NONE;
}
struct snd_ac97_bus_ops soc_ac97_ops = {
.read = jz4740_ac97_read,
.write = jz4740_ac97_write,
.warm_reset = jz4740_ac97_warm_reset,
.reset = jz4740_ac97_cold_reset,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_out = {
.name = "AC97 PCM Stereo out",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRTXPCDR,
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
DCMD_BURST32 | DCMD_WIDTH4,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_stereo_in = {
.name = "AC97 PCM Stereo in",
.dev_addr = __PREG(PCDR),
.drcmr = &DRCMRRXPCDR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST32 | DCMD_WIDTH4,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_out = {
.name = "AC97 Aux PCM (Slot 5) Mono out",
.dev_addr = __PREG(MODR),
.drcmr = &DRCMRTXMODR,
.dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
DCMD_BURST16 | DCMD_WIDTH2,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_aux_mono_in = {
.name = "AC97 Aux PCM (Slot 5) Mono in",
.dev_addr = __PREG(MODR),
.drcmr = &DRCMRRXMODR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST16 | DCMD_WIDTH2,
};
static struct jz4740_pcm_dma_params jz4740_ac97_pcm_mic_mono_in = {
.name = "AC97 Mic PCM (Slot 6) Mono in",
.dev_addr = __PREG(MCDR),
.drcmr = &DRCMRRXMCDR,
.dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
DCMD_BURST16 | DCMD_WIDTH2,
};
#ifdef CONFIG_PM
static int jz4740_ac97_suspend(struct platform_device *pdev,
struct snd_soc_cpu_dai *dai)
{
return 0;
}
static int jz4740_ac97_resume(struct platform_device *pdev,
struct snd_soc_cpu_dai *dai)
{
return 0;
}
#else
#define jz4740_ac97_suspend NULL
#define jz4740_ac97_resume NULL
#endif
static int jz4740_ac97_probe(struct platform_device *pdev)
{
int ret;
return 0;
}
static void jz4740_ac97_remove(struct platform_device *pdev)
{
}
static int jz4740_ac97_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_out;
else
cpu_dai->dma_data = &jz4740_ac97_pcm_stereo_in;
return 0;
}
static int jz4740_ac97_hw_aux_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_out;
else
cpu_dai->dma_data = &jz4740_ac97_pcm_aux_mono_in;
return 0;
}
static int jz4740_ac97_hw_mic_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return -ENODEV;
else
cpu_dai->dma_data = &jz4740_ac97_pcm_mic_mono_in;
return 0;
}
#define JZ4740_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
struct snd_soc_cpu_dai jz4740_ac97_dai[] = {
{
.name = "jz4740-ac97",
.id = 0,
.type = SND_SOC_DAI_AC97,
.probe = jz4740_ac97_probe,
.remove = jz4740_ac97_remove,
.suspend = jz4740_ac97_suspend,
.resume = jz4740_ac97_resume,
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 2,
.channels_max = 2,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {
.stream_name = "AC97 Capture",
.channels_min = 2,
.channels_max = 2,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = jz4740_ac97_hw_params,},
},
{
.name = "jz4740-ac97-aux",
.id = 1,
.type = SND_SOC_DAI_AC97,
.playback = {
.stream_name = "AC97 Aux Playback",
.channels_min = 1,
.channels_max = 1,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {
.stream_name = "AC97 Aux Capture",
.channels_min = 1,
.channels_max = 1,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = jz4740_ac97_hw_aux_params,},
},
{
.name = "jz4740-ac97-mic",
.id = 2,
.type = SND_SOC_DAI_AC97,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
.channels_max = 1,
.rates = JZ4740_AC97_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = jz4740_ac97_hw_mic_params,},
},
};
EXPORT_SYMBOL_GPL(jz4740_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
MODULE_AUTHOR("Richard");
MODULE_DESCRIPTION("AC97 driver for the Ingenic jz4740 chip");
MODULE_LICENSE("GPL");

View File

@ -1,21 +0,0 @@
/*
* linux/sound/soc/jz4750/jz4750-ac97.h
*
* 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.
*/
#ifndef _JZ4750_AC97_H
#define _JZ4750_AC97_H
#define JZ4750_DAI_AC97_HIFI 0
#define JZ4750_DAI_AC97_AUX 1
#define JZ4750_DAI_AC97_MIC 2
extern struct snd_soc_cpu_dai jz4750_ac97_dai[3];
/* platform data */
extern struct snd_ac97_bus_ops jz4750_ac97_ops;
#endif

View File

@ -1,311 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include "jz4750-pcm.h"
#include "jz4750-i2s.h"
#include "../codecs/jzdlv.h"
static struct jz4750_dma_client jz4750_dma_client_out = {
.name = "I2S PCM Stereo out"
};
static struct jz4750_dma_client jz4750_dma_client_in = {
.name = "I2S PCM Stereo in"
};
static struct jz4750_pcm_dma_params jz4750_i2s_pcm_stereo_out = {
.client = &jz4750_dma_client_out,
.channel = DMA_ID_AIC_TX,
.dma_addr = AIC_DR,
.dma_size = 2,
};
static struct jz4750_pcm_dma_params jz4750_i2s_pcm_stereo_in = {
.client = &jz4750_dma_client_in,
.channel = DMA_ID_AIC_RX,
.dma_addr = AIC_DR,
.dma_size = 2,
};
static int jz4750_i2s_startup(struct snd_pcm_substream *substream)
{
/*struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;*/
return 0;
}
static int jz4750_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
/* 1 : ac97 , 0 : i2s */
break;
case SND_SOC_DAIFMT_LEFT_J:
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* 0 : slave */
break;
case SND_SOC_DAIFMT_CBM_CFS:
/* 1 : master */
break;
default:
break;
}
return 0;
}
/*
* Set Jz4750 Clock source
*/
static int jz4750_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq, int dir)
{
return 0;
}
static void jz4750_snd_tx_ctrl(int on)
{
if (on) {
/* enable replay */
__i2s_enable_transmit_dma();
__i2s_enable_replay();
__i2s_enable();
} else {
/* disable replay & capture */
__i2s_disable_replay();
__i2s_disable_record();
__i2s_disable_receive_dma();
__i2s_disable_transmit_dma();
__i2s_disable();
}
}
static void jz4750_snd_rx_ctrl(int on)
{
if (on) {
/* enable capture */
__i2s_enable_receive_dma();
__i2s_enable_record();
__i2s_enable();
} else {
/* disable replay & capture */
__i2s_disable_replay();
__i2s_disable_record();
__i2s_disable_receive_dma();
__i2s_disable_transmit_dma();
__i2s_disable();
}
}
static int jz4750_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
//struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
int channels = params_channels(params);
jz4750_snd_rx_ctrl(0);
jz4750_snd_rx_ctrl(0);
write_codec_file_bit(5, 0, 7);//PMR1.SB_DAC->0
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
//cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_out;
rtd->dai->cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_out;
if (channels == 1)
__aic_enable_mono2stereo();
else
__aic_disable_mono2stereo();
} else
rtd->dai->cpu_dai->dma_data = &jz4750_i2s_pcm_stereo_in;
#if 1
switch (channels) {
case 1:
write_codec_file_bit(1, 1, 6);//CR1.MONO->1 for Mono
break;
case 2:
write_codec_file_bit(1, 0, 6);//CR1.MONO->0 for Stereo
break;
}
#endif
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
__i2s_set_transmit_trigger(4);
__i2s_set_receive_trigger(3);
__i2s_set_oss_sample_size(8);
__i2s_set_iss_sample_size(8);
break;
case SNDRV_PCM_FORMAT_S16_LE:
/* playback sample:16 bits, burst:16 bytes */
__i2s_set_transmit_trigger(4);
/* capture sample:16 bits, burst:16 bytes */
__i2s_set_receive_trigger(3);
__i2s_set_oss_sample_size(16);
__i2s_set_iss_sample_size(16);
/* DAC path and ADC path */
write_codec_file(2, 0x00);
break;
}
return 0;
}
static int jz4750_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
jz4750_snd_rx_ctrl(1);
else
jz4750_snd_tx_ctrl(1);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
jz4750_snd_rx_ctrl(0);
else
jz4750_snd_tx_ctrl(0);
break;
default:
ret = -EINVAL;
}
return ret;
}
static void jz4750_i2s_shutdown(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
} else {
}
return;
}
static int jz4750_i2s_probe(struct platform_device *pdev)
{
__i2s_internal_codec();
__i2s_as_slave();
__i2s_select_i2s();
__aic_select_i2s();
mdelay(2);
__i2s_disable();
mdelay(2);
REG_AIC_I2SCR = 0x10;
__i2s_disable();
__i2s_internal_codec();
__i2s_as_slave();
__i2s_select_i2s();
__aic_select_i2s();
__i2s_set_oss_sample_size(16);
__i2s_set_iss_sample_size(16);
__aic_play_lastsample();
__i2s_disable_record();
__i2s_disable_replay();
__i2s_disable_loopback();
__i2s_set_transmit_trigger(7);
__i2s_set_receive_trigger(7);
jz4750_snd_tx_ctrl(0);
jz4750_snd_rx_ctrl(0);
return 0;
}
#ifdef CONFIG_PM
static int jz4750_i2s_suspend(struct platform_device *dev,
struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
return 0;
}
static int jz4750_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
return 0;
}
#else
#define jz4750_i2s_suspend NULL
#define jz4750_i2s_resume NULL
#endif
#define JZ4750_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_12000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_24000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000)
struct snd_soc_dai jz4750_i2s_dai = {
.name = "jz4750-i2s",
.id = 0,
.type = SND_SOC_DAI_I2S,
.probe = jz4750_i2s_probe,
.suspend = jz4750_i2s_suspend,
.resume = jz4750_i2s_resume,
.playback = {
.channels_min = 1,
.channels_max = 2,
.rates = JZ4750_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.capture = {
.channels_min = 1,
.channels_max = 2,
.rates = JZ4750_I2S_RATES,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.startup = jz4750_i2s_startup,
.shutdown = jz4750_i2s_shutdown,
.trigger = jz4750_i2s_trigger,
.hw_params = jz4750_i2s_hw_params,},
.dai_ops = {
.set_fmt = jz4750_i2s_set_dai_fmt,
.set_sysclk = jz4750_i2s_set_dai_sysclk,
},
};
EXPORT_SYMBOL_GPL(jz4750_i2s_dai);
/* Module information */
MODULE_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn");
MODULE_DESCRIPTION("jz4750 I2S SoC Interface");
MODULE_LICENSE("GPL");

View File

@ -1,18 +0,0 @@
/*
* 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.
*/
#ifndef _JZ4750_I2S_H
#define _JZ4750_I2S_H
/* jz4750 DAI ID's */
#define JZ4750_DAI_I2S 0
/* I2S clock */
#define JZ4750_I2S_SYSCLK 0
extern struct snd_soc_dai jz4750_i2s_dai;
#endif

View File

@ -1,687 +0,0 @@
/*
*
* 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/module.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <asm/io.h>
#include "jz4750-pcm.h"
static long sum_bytes = 0;
static int first_transfer = 0;
static int printk_flag = 0;
static int tran_bit = 0;
#ifdef CONFIG_SND_OSSEMUL
static int hw_params_cnt = 0;
#endif
struct jz4750_dma_buf_aic {
struct jz4750_dma_buf_aic *next;
int size; /* buffer size in bytes */
dma_addr_t data; /* start of DMA data */
dma_addr_t ptr; /* where the DMA got to [1] */
void *id; /* client's id */
};
struct jz4750_runtime_data {
spinlock_t lock;
int state;
int aic_dma_flag; /* start dma transfer or not */
unsigned int dma_loaded;
unsigned int dma_limit;
unsigned int dma_period;
dma_addr_t dma_start;
dma_addr_t dma_pos;
dma_addr_t dma_end;
struct jz4750_pcm_dma_params *params;
dma_addr_t user_cur_addr; /* user current write buffer start address */
unsigned int user_cur_len; /* user current write buffer length */
/* buffer list and information */
struct jz4750_dma_buf_aic *curr; /* current dma buffer */
struct jz4750_dma_buf_aic *next; /* next buffer to load */
struct jz4750_dma_buf_aic *end; /* end of queue */
};
/* identify hardware playback capabilities */
static const struct snd_pcm_hardware jz4750_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_U16_LE |
SNDRV_PCM_FMTBIT_U8 |
SNDRV_PCM_FMTBIT_S8,
.rates = SNDRV_PCM_RATE_8000_96000/*0x3fe*/,
.rate_min = 8000,
.rate_max = 96000,
.channels_min = 1,//2
.channels_max = 2,
.buffer_bytes_max = 128 * 1024,//16 * 1024
.period_bytes_min = PAGE_SIZE,
.period_bytes_max = PAGE_SIZE * 2,
.periods_min = 2,
.periods_max = 128,//16,
.fifo_size = 32,
};
/* jz4750__dma_buf_enqueue
*
* queue an given buffer for dma transfer.
*
* data the physical address of the buffer data
* size the size of the buffer in bytes
*
*/
static int jz4750_dma_buf_enqueue(struct jz4750_runtime_data *prtd, dma_addr_t data, int size)
{
struct jz4750_dma_buf_aic *aic_buf;
aic_buf = kzalloc(sizeof(struct jz4750_dma_buf_aic), GFP_KERNEL);
if (aic_buf == NULL) {
printk("aic buffer allocate failed,no memory!\n");
return -ENOMEM;
}
aic_buf->next = NULL;
aic_buf->data = aic_buf->ptr = data;
aic_buf->size = size;
if( prtd->curr == NULL) {
prtd->curr = aic_buf;
prtd->end = aic_buf;
prtd->next = NULL;
} else {
if (prtd->end == NULL)
printk("prtd->end is NULL\n");
prtd->end->next = aic_buf;
prtd->end = aic_buf;
}
/* if necessary, update the next buffer field */
if (prtd->next == NULL)
prtd->next = aic_buf;
return 0;
}
void audio_start_dma(struct jz4750_runtime_data *prtd, int mode)
{
unsigned long flags;
struct jz4750_dma_buf_aic *aic_buf;
int channel;
switch (mode) {
case DMA_MODE_WRITE:
/* free cur aic_buf */
if (first_transfer == 1) {
first_transfer = 0;
} else {
aic_buf = prtd->curr;
if (aic_buf != NULL) {
prtd->curr = aic_buf->next;
prtd->next = aic_buf->next;
aic_buf->next = NULL;
kfree(aic_buf);
aic_buf = NULL;
}
}
aic_buf = prtd->next;
channel = prtd->params->channel;
if (aic_buf) {
flags = claim_dma_lock();
disable_dma(channel);
jz_set_alsa_dma(channel, mode, tran_bit);
set_dma_addr(channel, aic_buf->data);
set_dma_count(channel, aic_buf->size);
enable_dma(channel);
release_dma_lock(flags);
prtd->aic_dma_flag |= AIC_START_DMA;
} else {
printk("next buffer is NULL for playback\n");
prtd->aic_dma_flag &= ~AIC_START_DMA;
return;
}
break;
case DMA_MODE_READ:
/* free cur aic_buf */
if (first_transfer == 1) {
first_transfer = 0;
} else {
aic_buf = prtd->curr;
if (aic_buf != NULL) {
prtd->curr = aic_buf->next;
prtd->next = aic_buf->next;
aic_buf->next = NULL;
kfree(aic_buf);
aic_buf = NULL;
}
}
aic_buf = prtd->next;
channel = prtd->params->channel;
if (aic_buf) {
flags = claim_dma_lock();
disable_dma(channel);
jz_set_alsa_dma(channel, mode, tran_bit);
set_dma_addr(channel, aic_buf->data);
set_dma_count(channel, aic_buf->size);
enable_dma(channel);
release_dma_lock(flags);
prtd->aic_dma_flag |= AIC_START_DMA;
} else {
printk("next buffer is NULL for capture\n");
prtd->aic_dma_flag &= ~AIC_START_DMA;
return;
}
break;
}
}
/*
* place a dma buffer onto the queue for the dma system to handle.
*/
static void jz4750_pcm_enqueue(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd = runtime->private_data;
/*struct snd_dma_buffer *buf = &substream->dma_buffer;*/
dma_addr_t pos = prtd->dma_pos;
int ret;
while (prtd->dma_loaded < prtd->dma_limit) {
unsigned long len = prtd->dma_period;
if ((pos + len) > prtd->dma_end) {
len = prtd->dma_end - pos;
}
ret = jz4750_dma_buf_enqueue(prtd, pos, len);
if (ret == 0) {
prtd->dma_loaded++;
pos += prtd->dma_period;
if (pos >= prtd->dma_end)
pos = prtd->dma_start;
} else
break;
}
prtd->dma_pos = pos;
}
/*
* call the function:jz4750_pcm_dma_irq() after DMA has transfered the current buffer
*/
static irqreturn_t jz4750_pcm_dma_irq(int dma_ch, void *dev_id)
{
struct snd_pcm_substream *substream = dev_id;
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd = runtime->private_data;
/*struct jz4750_dma_buf_aic *aic_buf = prtd->curr;*/
int channel = prtd->params->channel;
unsigned long flags;
disable_dma(channel);
prtd->aic_dma_flag &= ~AIC_START_DMA;
/* must clear TT bit in DCCSR to avoid interrupt again */
if (__dmac_channel_transmit_end_detected(channel)) {
__dmac_channel_clear_transmit_end(channel);
}
if (__dmac_channel_transmit_halt_detected(channel)) {
__dmac_channel_clear_transmit_halt(channel);
}
if (__dmac_channel_address_error_detected(channel)) {
__dmac_channel_clear_address_error(channel);
}
if (substream)
snd_pcm_period_elapsed(substream);
spin_lock(&prtd->lock);
prtd->dma_loaded--;
if (prtd->state & ST_RUNNING) {
jz4750_pcm_enqueue(substream);
}
spin_unlock(&prtd->lock);
local_irq_save(flags);
if (prtd->state & ST_RUNNING) {
if (prtd->dma_loaded) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
audio_start_dma(prtd, DMA_MODE_WRITE);
else
audio_start_dma(prtd, DMA_MODE_READ);
}
}
local_irq_restore(flags);
return IRQ_HANDLED;
}
/* some parameter about DMA operation */
static int jz4750_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct jz4750_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
size_t totbytes = params_buffer_bytes(params);
int ret;
#ifdef CONFIG_SND_OSSEMUL
if (hw_params_cnt)
return 0;
else
hw_params_cnt++ ;
#endif
if (!dma)
return 0;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
tran_bit = 8;
break;
case SNDRV_PCM_FORMAT_S16_LE:
tran_bit = 16;
break;
}
/* prepare DMA */
prtd->params = dma;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = jz_request_dma(DMA_ID_AIC_TX, prtd->params->client->name,
jz4750_pcm_dma_irq, IRQF_DISABLED, substream);
if (ret < 0)
return ret;
prtd->params->channel = ret;
} else {
ret = jz_request_dma(DMA_ID_AIC_RX, prtd->params->client->name,
jz4750_pcm_dma_irq, IRQF_DISABLED, substream);
if (ret < 0)
return ret;
prtd->params->channel = ret;
}
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = totbytes;
spin_lock_irq(&prtd->lock);
prtd->dma_loaded = 0;
prtd->aic_dma_flag = 0;
prtd->dma_limit = runtime->hw.periods_min;
prtd->dma_period = params_period_bytes(params);
prtd->dma_start = runtime->dma_addr;
prtd->dma_pos = prtd->dma_start;
prtd->dma_end = prtd->dma_start + totbytes;
prtd->curr = NULL;
prtd->next = NULL;
prtd->end = NULL;
sum_bytes = 0;
first_transfer = 1;
printk_flag = 0;
__dmac_disable_descriptor(prtd->params->channel);
__dmac_channel_disable_irq(prtd->params->channel);
spin_unlock_irq(&prtd->lock);
return ret;
}
static int jz4750_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct jz4750_runtime_data *prtd = substream->runtime->private_data;
snd_pcm_set_runtime_buffer(substream, NULL);
if (prtd->params) {
jz_free_dma(prtd->params->channel);
prtd->params = NULL;
}
return 0;
}
/* set some dma para for playback/capture */
static int jz4750_dma_ctrl(int channel)
{
disable_dma(channel);
/* must clear TT bit in DCCSR to avoid interrupt again */
if (__dmac_channel_transmit_end_detected(channel)) {
__dmac_channel_clear_transmit_end(channel);
}
if (__dmac_channel_transmit_halt_detected(channel)) {
__dmac_channel_clear_transmit_halt(channel);
}
if (__dmac_channel_address_error_detected(channel)) {
__dmac_channel_clear_address_error(channel);
}
return 0;
}
static int jz4750_pcm_prepare(struct snd_pcm_substream *substream)
{
struct jz4750_runtime_data *prtd = substream->runtime->private_data;
int ret = 0;
/* return if this is a bufferless transfer e.g */
if (!prtd->params)
return 0;
/* flush the DMA channel and DMA channel bit check */
jz4750_dma_ctrl(prtd->params->channel);
prtd->dma_loaded = 0;
prtd->dma_pos = prtd->dma_start;
/* enqueue dma buffers */
jz4750_pcm_enqueue(substream);
return ret;
}
static int jz4750_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd = runtime->private_data;
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
prtd->state |= ST_RUNNING;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
audio_start_dma(prtd, DMA_MODE_WRITE);
} else {
audio_start_dma(prtd, DMA_MODE_READ);
}
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
prtd->state &= ~ST_RUNNING;
break;
case SNDRV_PCM_TRIGGER_RESUME:
printk(" RESUME \n");
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
printk(" RESTART \n");
break;
default:
ret = -EINVAL;
}
return ret;
}
static snd_pcm_uframes_t
jz4750_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd = runtime->private_data;
struct jz4750_dma_buf_aic *aic_buf = prtd->curr;
long count,res;
dma_addr_t ptr;
snd_pcm_uframes_t x;
int channel = prtd->params->channel;
spin_lock(&prtd->lock);
#if 1
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
count = get_dma_residue(channel);
count = aic_buf->size - count;
ptr = aic_buf->data + count;
res = ptr - prtd->dma_start;
} else {
count = get_dma_residue(channel);
count = aic_buf->size - count;
ptr = aic_buf->data + count;
res = ptr - prtd->dma_start;
}
# else
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) {
count = get_dma_residue(channel);
count = aic_buf->size - count;
ptr = aic_buf->data + count;
REG_DMAC_DSAR(channel) = ptr;
res = ptr - prtd->dma_start;
} else {
ptr = REG_DMAC_DSAR(channel);
if (ptr == 0x0)
printk("\ndma address is 00000000 in running!\n");
res = ptr - prtd->dma_start;
}
} else {
if ((prtd->aic_dma_flag & AIC_START_DMA) == 0) {
count = get_dma_residue(channel);
count = aic_buf->size - count;
ptr = aic_buf->data + count;
REG_DMAC_DTAR(channel) = ptr;
res = ptr - prtd->dma_start;
} else {
ptr = REG_DMAC_DTAR(channel);
if (ptr == 0x0)
printk("\ndma address is 00000000 in running!\n");
res = ptr - prtd->dma_start;
}
}
#endif
spin_unlock(&prtd->lock);
x = bytes_to_frames(runtime, res);
if (x == runtime->buffer_size)
x = 0;
return x;
}
static int jz4750_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd;
#ifdef CONFIG_SND_OSSEMUL
hw_params_cnt = 0;
#endif
REG_DMAC_DMACKE(0) = 0x3f;
REG_DMAC_DMACKE(1) = 0x3f;
snd_soc_set_runtime_hwparams(substream, &jz4750_pcm_hardware);
prtd = kzalloc(sizeof(struct jz4750_runtime_data), GFP_KERNEL);
if (prtd == NULL)
return -ENOMEM;
spin_lock_init(&prtd->lock);
runtime->private_data = prtd;
return 0;
}
static int jz4750_pcm_close(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4750_runtime_data *prtd = runtime->private_data;
struct jz4750_dma_buf_aic *aic_buf = NULL;
#ifdef CONFIG_SND_OSSEMUL
hw_params_cnt = 0;
#endif
if (prtd)
aic_buf = prtd->curr;
while (aic_buf != NULL) {
prtd->curr = aic_buf->next;
prtd->next = aic_buf->next;
aic_buf->next = NULL;
kfree(aic_buf);
aic_buf = NULL;
aic_buf = prtd->curr;
}
if (prtd) {
prtd->curr = NULL;
prtd->next = NULL;
prtd->end = NULL;
kfree(prtd);
}
return 0;
}
static int jz4750_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)//include/linux/mm.h
{
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long start;
unsigned long off;
u32 len;
int ret = -ENXIO;
off = vma->vm_pgoff << PAGE_SHIFT;
start = runtime->dma_addr;
len = PAGE_ALIGN((start & ~PAGE_MASK) + runtime->dma_bytes);
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len) {
return -EINVAL;
}
off += start;
vma->vm_pgoff = off >> PAGE_SHIFT;
vma->vm_flags |= VM_IO;
#if defined(CONFIG_MIPS32)
pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
/* pgprot_val(vma->vm_page_prot) |= _CACHE_CACHABLE_NONCOHERENT; */
#endif
ret = io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
return ret;
}
struct snd_pcm_ops jz4750_pcm_ops = {
.open = jz4750_pcm_open,
.close = jz4750_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = jz4750_pcm_hw_params,
.hw_free = jz4750_pcm_hw_free,
.prepare = jz4750_pcm_prepare,
.trigger = jz4750_pcm_trigger,
.pointer = jz4750_pcm_pointer,
.mmap = jz4750_pcm_mmap,
};
static int jz4750_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
struct snd_dma_buffer *buf = &substream->dma_buffer;
size_t size = jz4750_pcm_hardware.buffer_bytes_max;
buf->dev.type = SNDRV_DMA_TYPE_DEV;
buf->dev.dev = pcm->card->dev;
buf->private_data = NULL;
/*buf->area = dma_alloc_coherent(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);*/
buf->area = dma_alloc_noncoherent(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
if (!buf->area)
return -ENOMEM;
buf->bytes = size;
return 0;
}
static void jz4750_pcm_free_dma_buffers(struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
for (stream = 0; stream < 2; stream++) {
substream = pcm->streams[stream].substream;
if (!substream)
continue;
buf = &substream->dma_buffer;
if (!buf->area)
continue;
dma_free_noncoherent(pcm->card->dev, buf->bytes,
buf->area, buf->addr);
buf->area = NULL;
}
}
static u64 jz4750_pcm_dmamask = DMA_32BIT_MASK;
int jz4750_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
struct snd_pcm *pcm)
{
int ret = 0;
if (!card->dev->dma_mask)
card->dev->dma_mask = &jz4750_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_32BIT_MASK;
if (dai->playback.channels_min) {
ret = jz4750_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
if (dai->capture.channels_min) {
ret = jz4750_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto out;
}
out:
return ret;
}
struct snd_soc_platform jz4750_soc_platform = {
.name = "jz4750-audio",
.pcm_ops = &jz4750_pcm_ops,
.pcm_new = jz4750_pcm_new,
.pcm_free = jz4750_pcm_free_dma_buffers,
};
EXPORT_SYMBOL_GPL(jz4750_soc_platform);
MODULE_AUTHOR("Richard");
MODULE_DESCRIPTION("Ingenic Jz4750 PCM DMA module");
MODULE_LICENSE("GPL");

View File

@ -1,33 +0,0 @@
/*
*
* 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.
*/
#ifndef _JZ4750_PCM_H
#define _JZ4750_PCM_H
#include <asm/jzsoc.h>
#define ST_RUNNING (1<<0)
#define ST_OPENED (1<<1)
#define AIC_START_DMA (1<<0)
#define AIC_END_DMA (1<<1)
struct jz4750_dma_client {
char *name;
};
struct jz4750_pcm_dma_params {
struct jz4750_dma_client *client; /* stream identifier */
int channel; /* Channel ID */
dma_addr_t dma_addr;
int dma_size; /* Size of the DMA transfer */
};
/* platform data */
extern struct snd_soc_platform jz4750_soc_platform;
#endif

View File

@ -54,118 +54,6 @@ index 2389352..24dcb18 100644
#define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000) #define SNDRV_PCM_RATE_8000_48000 (SNDRV_PCM_RATE_8000_44100|SNDRV_PCM_RATE_48000)
#define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\ #define SNDRV_PCM_RATE_8000_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\
SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 72cfd47..5ae0a2d 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2076,6 +2076,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
+#if 0
snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
{
struct snd_pcm_runtime *runtime;
@@ -2091,6 +2092,99 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u
return -EINVAL;
return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
}
+#else
+snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
+{
+ struct snd_pcm_runtime *runtime;
+ int nonblock;
+
+ snd_pcm_sframes_t tmp_frames;
+ snd_pcm_sframes_t final_frames;
+ int channels;
+
+ snd_assert(substream != NULL, return -ENXIO);
+ runtime = substream->runtime;
+ snd_assert(runtime != NULL, return -ENXIO);
+ snd_assert(substream->ops->copy != NULL || runtime->dma_area != NULL, return -EINVAL);
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+
+ nonblock = !!(substream->f_flags & O_NONBLOCK);
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
+ return -EINVAL;
+
+ /*
+ * mono capture process for no mono codec
+ * function codec such as ipcood and dlv
+ */
+
+ tmp_frames = snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
+
+ channels = runtime->channels;
+
+ if (channels == 1) {
+ short *tmpbuf = kcalloc(tmp_frames, sizeof(short), GFP_KERNEL);
+ short *src, *dst, *end;
+
+ memcpy(tmpbuf, buf, frames_to_bytes(runtime, tmp_frames));
+
+ src = (short *)buf;
+ dst = (short *)tmpbuf;
+ end = dst + tmp_frames - 1;
+
+ src++;
+ dst++;
+ dst++;
+ final_frames = 1;
+ while (dst <= end) {
+ *src = *dst;
+ final_frames++;
+ src++;
+ dst++;
+ dst++;
+ }
+ tmp_frames = final_frames;
+ kfree(tmpbuf);
+
+#if 0
+ /* when i have time, i will try the code, no kcalloc */
+ snd_assert(runtime->dma_area, return -EFAULT);
+ if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
+ return -EFAULT;
+
+ unsigned int up_bytes = frames_to_bytes(runtime, frames);
+
+ int while_cnt = 4;
+ int while_all = up_bytes - 2;
+
+ while (while_cnt <= while_all) {
+ //printk("[%d = %d]\n",(while_cnt/2),while_cnt);
+ buf[(while_cnt/2)] = buf[while_cnt];
+ //printk("[%d = %d]\n",((while_cnt/2)+1),(while_cnt+1));
+ buf[((while_cnt/2)+1)] = buf[(while_cnt+1)];
+ while_cnt += 4;
+#if 0
+ buf[2] = buf[4];
+ buf[3] = buf[5];
+
+ buf[4] = buf[8];
+ buf[5] = buf[9];
+
+ buf[6] = buf[12];
+ buf[7] = buf[13];
+
+ buf[8] = buf[16];
+ buf[9] = buf[17];
+#endif
+ }
+ /* when i have time, i will try the code, no kcalloc */
+#endif
+
+ }
+
+ return tmp_frames;
+}
+#endif
EXPORT_SYMBOL(snd_pcm_lib_read);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index ac2150e..2a57ab7 100644 index ac2150e..2a57ab7 100644
--- a/sound/core/pcm_native.c --- a/sound/core/pcm_native.c
@ -181,30 +69,12 @@ index ac2150e..2a57ab7 100644
-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, -static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
- 48000, 64000, 88200, 96000, 176400, 192000 }; - 48000, 64000, 88200, 96000, 176400, 192000 };
+static unsigned int rates[] = { 5512, 8000, 11025, 12000, 16000, 22050, 24000, +static unsigned int rates[] = { 5512, 8000, 11025, 12000, 16000, 22050, 24000,
+ 32000, 44100, 48000, 64000, 88200, 96000, + 32000, 44100, 48000, 64000, 88200, 96000,
+ 176400, 192000 }; + 176400, 192000 };
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
.count = ARRAY_SIZE(rates), .count = ARRAY_SIZE(rates),
@@ -1764,9 +1765,17 @@ static int snd_pcm_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_pcm_hardware *hw = rule->private;
+#if 0
return snd_interval_list(hw_param_interval(params, rule->var),
snd_pcm_known_rates.count,
snd_pcm_known_rates.list, hw->rates);
+#else
+ //printk("hw->rates=0x%08x\n",hw->rates);//0x3b6
+ hw->rates = 0x3fe;//12KHz and 24KHz bits are all zero,you need set 1
+ return snd_interval_list(hw_param_interval(params, rule->var),
+ snd_pcm_known_rates.count,
+ snd_pcm_known_rates.list, hw->rates);
+#endif
}
static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index d3e786a..a5335f4 100644 index d3e786a..a5335f4 100644
--- a/sound/soc/Kconfig --- a/sound/soc/Kconfig
@ -230,22 +100,17 @@ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bbc97fd..493e216 100644 index bbc97fd..493e216 100644
--- a/sound/soc/codecs/Kconfig --- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig
@@ -176,3 +176,15 @@ config SND_SOC_WM9712 @@ -179,3 +179,15 @@ config SND_SOC_WM9712
config SND_SOC_WM9713 config SND_SOC_WM9713
tristate tristate
+ +
+config SND_SOC_ICODEC +config SND_SOC_JZCODEC
+ tristate "Jz4740 internal codec" + tristate "JZ4720/JZ4740 SoC internal codec"
+ depends on SND_SOC && SND_JZ4740_SOC_PAVO && SND_JZ4740_SOC_I2S + depends on SND_SOC && SOC_JZ4740
+ help + help
+ Say Y if you want to use internal codec on Ingenic Jz4740 PAVO board. + Say Y if you want to use internal codec on Ingenic JZ4720/JZ4740 based
+ + boards.
+config SND_SOC_DLV
+ tristate "Jz4750 internal codec"
+ depends on SND_SOC && SND_JZ4750_SOC_APUS && SND_JZ4750_SOC_I2S
+ help
+ Say Y if you want to use internal codec on Ingenic Jz4750 APUS board.
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8b75305..f053c15 100644 index 8b75305..f053c15 100644
--- a/sound/soc/codecs/Makefile --- a/sound/soc/codecs/Makefile
@ -262,7 +127,7 @@ index 8b75305..f053c15 100644
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_ICODEC) += snd-soc-jzcodec.o +obj-$(CONFIG_SND_SOC_JZCODEC) += snd-soc-jzcodec.o
-- --
1.5.6.5 1.5.6.5

View File

@ -0,0 +1,229 @@
--- /opt/Projects/linux-2.6/sound/soc/soc-core.c 2009-09-02 16:48:38.000000000 +0200
+++ ./soc-core.c 2009-09-15 03:23:13.000000000 +0200
@@ -500,8 +500,8 @@
if (cpu_dai->ops->hw_params) {
ret = cpu_dai->ops->hw_params(substream, params, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: interface %s hw params failed\n",
- cpu_dai->name);
+ printk(KERN_ERR "asoc: interface %s hw params failed: %d\n",
+ cpu_dai->name, ret);
goto interface_err;
}
}
@@ -842,7 +842,7 @@
* DAIs currently; we can't do this per link since some AC97
* codecs have non-AC97 DAIs.
*/
- if (!ac97)
+ if (!ac97) {
for (i = 0; i < card->num_links; i++) {
found = 0;
list_for_each_entry(dai, &dai_list, list)
@@ -856,6 +856,7 @@
return;
}
}
+ }
/* Note that we do not current check for codec components */
@@ -1263,11 +1264,11 @@
*
* Returns 1 for change else 0.
*/
-int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
- unsigned short mask, unsigned short value)
+int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int mask, unsigned int value)
{
int change;
- unsigned short old, new;
+ unsigned int old, new;
mutex_lock(&io_mutex);
old = snd_soc_read(codec, reg);
@@ -1293,11 +1294,11 @@
*
* Returns 1 for change else 0.
*/
-int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
- unsigned short mask, unsigned short value)
+int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int mask, unsigned int value)
{
int change;
- unsigned short old, new;
+ unsigned int old, new;
mutex_lock(&io_mutex);
old = snd_soc_read(codec, reg);
@@ -1586,7 +1587,7 @@
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val, bitmask;
+ unsigned int val, bitmask;
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
@@ -1615,8 +1616,8 @@
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val;
- unsigned short mask, bitmask;
+ unsigned int val;
+ unsigned int mask, bitmask;
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
@@ -1652,7 +1653,7 @@
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short reg_val, val, mux;
+ unsigned int reg_val, val, mux;
reg_val = snd_soc_read(codec, e->reg);
val = (reg_val >> e->shift_l) & e->mask;
@@ -1691,8 +1692,8 @@
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val;
- unsigned short mask;
+ unsigned int val;
+ unsigned int mask;
if (ucontrol->value.enumerated.item[0] > e->max - 1)
return -EINVAL;
@@ -1852,7 +1853,7 @@
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- unsigned short val, val2, val_mask;
+ unsigned int val, val2, val_mask;
val = (ucontrol->value.integer.value[0] & mask);
if (invert)
@@ -1958,7 +1959,7 @@
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
int err;
- unsigned short val, val2, val_mask;
+ unsigned int val, val2, val_mask;
val_mask = mask << shift;
val = (ucontrol->value.integer.value[0] & mask);
@@ -2050,7 +2051,7 @@
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int reg = mc->reg;
int min = mc->min;
- unsigned short val;
+ unsigned int val;
val = (ucontrol->value.integer.value[0]+min) & 0xff;
val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
@@ -2251,6 +2252,7 @@
if (!dai->ops)
dai->ops = &null_dai_ops;
+
INIT_LIST_HEAD(&dai->list);
mutex_lock(&client_mutex);
--- /opt/Projects/linux-2.6/sound/soc/soc-dapm.c 2009-09-02 16:48:38.000000000 +0200
+++ ./soc-dapm.c 2009-09-08 17:49:09.000000000 +0200
@@ -268,7 +268,7 @@
static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
{
int change, power;
- unsigned short old, new;
+ unsigned int old, new;
struct snd_soc_codec *codec = widget->codec;
/* check for valid widgets */
@@ -1246,7 +1246,6 @@
/**
* snd_soc_dapm_new_widgets - add new dapm widgets
* @codec: audio codec
- *
* Checks the codec for any new dapm widgets and creates them if found.
*
* Returns 0 for success.
@@ -1336,7 +1335,8 @@
ucontrol->value.integer.value[0] =
(snd_soc_read(widget->codec, reg) >> shift) & mask;
- if (shift != rshift)
+
+ if (shift != rshift)
ucontrol->value.integer.value[1] =
(snd_soc_read(widget->codec, reg) >> rshift) & mask;
if (invert) {
@@ -1372,7 +1372,7 @@
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- unsigned short val, val2, val_mask;
+ unsigned int val, val2, val_mask;
int ret;
val = (ucontrol->value.integer.value[0] & mask);
@@ -1436,7 +1436,7 @@
{
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val, bitmask;
+ unsigned int val, bitmask;
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
;
@@ -1464,8 +1464,8 @@
{
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val, mux;
- unsigned short mask, bitmask;
+ unsigned int val, mux;
+ unsigned int mask, bitmask;
int ret = 0;
for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
@@ -1523,7 +1523,7 @@
{
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short reg_val, val, mux;
+ unsigned int reg_val, val, mux;
reg_val = snd_soc_read(widget->codec, e->reg);
val = (reg_val >> e->shift_l) & e->mask;
@@ -1563,8 +1563,8 @@
{
struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- unsigned short val, mux;
- unsigned short mask;
+ unsigned int val, mux;
+ unsigned int mask;
int ret = 0;
if (ucontrol->value.enumerated.item[0] > e->max - 1)
218,221c218,221
< int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
< unsigned short mask, unsigned short value);
< int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
< unsigned short mask, unsigned short value);
---
> int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned int reg,
> unsigned int mask, unsigned int value);
> int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg,
> unsigned int mask, unsigned int value);
495,496c495,496
< unsigned short reg;
< unsigned short reg2;
---
> unsigned int reg;
> unsigned int reg2;