1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-28 21:10:17 +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
* it under the terms of the GNU General Public License version 2 as
* 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
#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
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;
#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
tristate "SoC Audio for Ingenic jz4740 chip"
depends on (JZ4740_PAVO || JZ4725_DIPPER || JZ4720_VIRGO) && SND_SOC
tristate "SoC Audio for Ingenic JZ4740 SoC"
depends on SOC_JZ4740 && SND_SOC
help
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
to select the audio interfaces to support below.
config SND_JZ4740_SOC_PAVO
tristate "SoC Audio support for Ingenic Jz4740 PAVO board"
depends on SND_JZ4740_SOC
config SND_JZ4740_SOC_QI_LB60
tristate "SoC Audio support for Qi Hardware Ben Nanonote"
depends on SND_JZ4740_SOC && JZ4740_QI_LB60
select SND_JZ4740_SOC_I2S
select SND_SOC_JZCODEC
help
Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 PAVO 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.
Say Y if you want to add support for SoC audio of internal codec on Ingenic Jz4740 QI_LB60 board.
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"
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
#
snd-soc-jz4740-objs := jz4740-pcm.o
snd-soc-jz4740-ac97-objs := jz4740-ac97.o
snd-soc-jz4740-i2s-objs := jz4740-i2s.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
# 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
* 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/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>
@ -42,7 +43,7 @@ static struct jz4740_pcm_dma_params jz4740_i2s_pcm_stereo_in = {
.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_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,
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_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
int channels = params_channels(params);
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
/* int channels = params_channels(params); */
jz4740_snd_rx_ctrl(0);
jz4740_snd_rx_ctrl(0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
//cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out;
rtd->dai->cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out;
if (channels == 1)
cpu_dai->dma_data = &jz4740_i2s_pcm_stereo_out;
/*if (channels == 1)
__aic_enable_mono2stereo();
else
__aic_disable_mono2stereo();
__aic_disable_mono2stereo();*/
} 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)) {
case SNDRV_PCM_FORMAT_S8:
@ -162,7 +162,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
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;
switch (cmd) {
@ -189,7 +189,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
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) {
} else {
@ -198,7 +198,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream)
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_as_slave();
@ -232,8 +232,7 @@ static int jz4740_i2s_probe(struct platform_device *pdev)
}
#ifdef CONFIG_PM
static int jz4740_i2s_suspend(struct platform_device *dev,
struct snd_soc_dai *dai)
static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
@ -241,8 +240,7 @@ static int jz4740_i2s_suspend(struct platform_device *dev,
return 0;
}
static int jz4740_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai *dai)
static int jz4740_i2s_resume(struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
@ -256,15 +254,22 @@ static int jz4740_i2s_resume(struct platform_device *pdev,
#endif
#define JZ4740_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_16000 | SNDRV_PCM_RATE_22050 |\
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 = {
.name = "jz4740-i2s",
.id = 0,
.type = SND_SOC_DAI_I2S,
.probe = jz4740_i2s_probe,
.suspend = jz4740_i2s_suspend,
.resume = jz4740_i2s_resume,
@ -272,25 +277,32 @@ struct snd_soc_dai jz4740_i2s_dai = {
.channels_min = 1,
.channels_max = 2,
.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 = {
.channels_min = 1,
.channels_max = 2,
.rates = JZ4740_I2S_RATES,
.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,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
},
.ops = &snd_jz4740_i2s_dai_ops,
};
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_AUTHOR("Richard, cjfeng@ingenic.cn, www.ingenic.cn");
MODULE_DESCRIPTION("jz4740 I2S SoC Interface");

View File

View File

@ -12,7 +12,6 @@
#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>
@ -29,6 +28,29 @@ static int tran_bit = 0;
static int hw_params_cnt = 0;
#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 *next;
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_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_48000/*0x3fe*/,
.rate_min = 8000,
.rate_min = 48000,
.channels_min = 1,//2
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = 128 * 1024,//16 * 1024
.period_bytes_min = PAGE_SIZE,
@ -126,7 +146,7 @@ void audio_start_dma(struct jz4740_runtime_data *prtd, int mode)
unsigned long flags;
struct jz4740_dma_buf_aic *aic_buf;
int channel;
printk("%s:%s:%d\n",__FILE__,__FUNCTION__,__LINE__);
switch (mode) {
case DMA_MODE_WRITE:
/* free cur aic_buf */
@ -146,13 +166,11 @@ void audio_start_dma(struct jz4740_runtime_data *prtd, int mode)
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");
@ -179,13 +197,11 @@ void audio_start_dma(struct jz4740_runtime_data *prtd, int mode)
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");
@ -283,17 +299,10 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
struct jz4740_runtime_data *prtd = runtime->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);
int ret;
#ifdef CONFIG_SND_OSSEMUL
if (hw_params_cnt)
return 0;
else
hw_params_cnt++ ;
#endif
if (!dma)
return 0;
@ -343,7 +352,6 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
__dmac_disable_descriptor(prtd->params->channel);
__dmac_channel_disable_irq(prtd->params->channel);
spin_unlock_irq(&prtd->lock);
return ret;
}
@ -565,32 +573,8 @@ static int jz4740_pcm_mmap(struct snd_pcm_substream *substream,
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;
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
return 0;
}
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,
struct snd_pcm *pcm)
{
int ret = 0;
printk("pcm new\n");
if (!card->dev->dma_mask)
card->dev->dma_mask = &jz4740_pcm_dmamask;
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) {
ret = jz4740_pcm_preallocate_dma_buffer(pcm,
@ -684,6 +670,18 @@ struct snd_soc_platform 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_DESCRIPTION("Ingenic Jz4740 PCM DMA module");
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_96000 (SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_64000|\
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
index ac2150e..2a57ab7 100644
--- a/sound/core/pcm_native.c
@ -187,24 +75,6 @@ index ac2150e..2a57ab7 100644
const struct snd_pcm_hw_constraint_list snd_pcm_known_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
index d3e786a..a5335f4 100644
--- a/sound/soc/Kconfig
@ -230,22 +100,17 @@ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bbc97fd..493e216 100644
--- a/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
tristate
+
+config SND_SOC_ICODEC
+ tristate "Jz4740 internal codec"
+ depends on SND_SOC && SND_JZ4740_SOC_PAVO && SND_JZ4740_SOC_I2S
+config SND_SOC_JZCODEC
+ tristate "JZ4720/JZ4740 SoC internal codec"
+ depends on SND_SOC && SOC_JZ4740
+ help
+ Say Y if you want to use internal codec on Ingenic Jz4740 PAVO board.
+
+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.
+ Say Y if you want to use internal codec on Ingenic JZ4720/JZ4740 based
+ boards.
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8b75305..f053c15 100644
--- 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_WM9712) += snd-soc-wm9712.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

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;