blob: ff07416fc94569aa3a0870210c11663016743e89 [file] [log] [blame]
/*
* zx297520v3_es8312.c -- zx298501-dummycodec ALSA SoC Audio board driver
*
* Copyright (C) 2022, ZTE Corporation.
*
* Based on smdk_wm8994.c
*
* 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 <sound/pcm_params.h>
#include <sound/soc.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/delay.h>
//#include <sound/tlv.h>
//#include <sound/soc.h>
//#include <sound/jack.h>
//#include <sound/zx29_snd_platform.h>
//#include <mach/iomap.h>
//#include <mach/board.h>
#include <linux/of_gpio.h>
#include <linux/i2c.h>
#include <linux/of_gpio.h>
#include <linux/regmap.h>
#include "i2s.h"
#include "pub_debug_info.h"
#define ZX29_I2S_TOP_LOOP_REG 0x60
#if 1
#define ZXIC_MCLK 26000000
#define ZX29_AK4940_FREQ 26000000
#define ZXIC_PLL_CLKIN_MCLK 0
#define zx_reg_sync_write(v, a) \
do { \
iowrite32(v, a); \
} while (0)
#define zx_read_reg(addr) \
ioread32(addr)
#define zx_write_reg(addr, val) \
zx_reg_sync_write(val, addr)
struct zx29_board_data {
const char *name;
struct device *dev;
int codec_refclk;
int gpio_pwen;
int gpio_pdn;
void __iomem *sys_base_va;
};
//#define AON_WIFI_BT_CLK_CFG2 ((volatile unsigned int *)(ZX_TOP_CRM_BASE + 0x94))
/* Default ZX29s */
static struct zx29_board_data zx29_platform_data = {
.codec_refclk = ZX29_AK4940_FREQ,
};
static struct platform_device *zx29_snd_device;
static DEFINE_RAW_SPINLOCK(codec_pa_lock);
static int set_path_stauts_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static int get_path_stauts_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
#ifdef USE_ALSA_VOICE_FUNC
extern int zDrv_Audio_Printf(void *pFormat, ...);
extern int zDrvVp_GetVol_Wrap(void);
extern int zDrvVp_SetVol_Wrap(int volume);
extern int zDrvVp_GetPath_Wrap(void);
extern int zDrvVp_SetPath_Wrap(int path);
extern int zDrvVp_SetMute_Wrap(bool enable);
extern bool zDrvVp_GetMute_Wrap(void);
extern int zDrvVp_SetTone_Wrap(int toneNum);
static int vp_GetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_SetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_SetVol(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_GetVol(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_SetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_GetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_SetTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int vp_getTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int audio_GetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
static int audio_SetPath(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
//static const DECLARE_TLV_DB_SCALE(vp_path_tlv, 0, 300, 0);
static const char * const vpath_in_text[] = {
"handset", "speak", "headset", "bluetooth",
};
static const char *tone_class[] = {
"Lowpower", "Sms", "Callstd", "Alarm", "Calltime",
};
static const struct soc_enum vpath_in_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(vpath_in_text), vpath_in_text);
static const struct soc_enum tone_class_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tone_class), tone_class),
};
static const struct snd_kcontrol_new vp_snd_controls[] = {
SOC_ENUM_EXT("voice processing path select",vpath_in_enum,vp_GetPath,vp_SetPath),
//SOC_SINGLE_EXT_TLV("voice processing path Volume",0, 5, 5, 0,vp_GetVol, vp_SetVol,vp_path_tlv),
SOC_SINGLE_EXT("voice processing path Volume",0, 5, 5, 0,vp_GetVol, vp_SetVol),
SOC_SINGLE_EXT("voice uplink mute", 0, 1, 1, 0,vp_GetMute, vp_SetMute),
SOC_ENUM_EXT("voice tone sel", tone_class_enum[0], vp_getTone, vp_SetTone),
SOC_SINGLE_BOOL_EXT("path stauts dump", 0,get_path_stauts_switch, set_path_stauts_switch),
SOC_ENUM_EXT("audio path select",vpath_in_enum,audio_GetPath,audio_SetPath),
};
static int curtonetype = 0;
static int vp_getTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = curtonetype;
return 0;
}
static int vp_SetTone(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int vol = 0,ret = 0, tonenum;
tonenum = ucontrol->value.integer.value[0];
curtonetype = tonenum;
//printk("Alsa vp_SetTone tonenum=%d\n", tonenum);
//ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetTone_Wrap)(tonenum);
if(ret < 0)
{
printk(KERN_ERR "vp_SetTone fail = %d\n", tonenum);
return ret;
}
return 0;
}
static int vp_SetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
int enable = 0,ret = 0;
enable = ucontrol->value.integer.value[0];
//ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetMute_Wrap)(enable);
if(ret < 0)
{
printk(KERN_ERR "vp_SetMute fail = %d\n",enable);
return ret;
}
return 0;
}
static int vp_GetMute(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
//ucontrol->value.integer.value[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetMute_Wrap)();
return 0;
}
static int vp_SetVol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int vol = 0,ret = 0;
vol = ucontrol->value.integer.value[0];
//ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetVol_Wrap)(vol);
if(ret < 0)
{
printk(KERN_ERR "vp_SetVol fail = %d\n",vol);
return ret;
}
return 0;
}
static int vp_GetVol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
//ucontrol->value.integer.value[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetVol_Wrap)();
return 0;
}
static int vp_GetPath(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
//ucontrol->value.enumerated.item[0] = CPPS_FUNC(cpps_callbacks, zDrvVp_GetPath_Wrap)();
return 0;
}
static int vp_SetPath(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int ret = 0,path = 0;
unsigned long flags;
path = ucontrol->value.enumerated.item[0];
//ret = CPPS_FUNC(cpps_callbacks, zDrvVp_SetPath_Wrap)(path);
if(ret < 0)
{
printk(KERN_ERR "vp_SetPath fail = %d\n",path);
return ret;
}
#ifdef _USE_7520V3_PHONE_TYPE_C31F
switch (path) {
case 0:
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
mdelay(1);
gpio_set_value(ZX29_GPIO_40, GPIO_LOW);
break;
case 1:
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
mdelay(1);
raw_spin_lock_irqsave(&codec_pa_lock, flags);
gpio_set_value(ZX29_GPIO_39, GPIO_HIGH);
udelay(2);
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
udelay(2);
gpio_set_value(ZX29_GPIO_39, GPIO_HIGH);
raw_spin_unlock_irqrestore(&codec_pa_lock, flags);
gpio_set_value(ZX29_GPIO_40, GPIO_HIGH);
break;
case 2:
break;
case 3:
break;
default:
break;
}
#endif
return 0;
}
static int curpath = 0;
static int audio_GetPath(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.enumerated.item[0] = curpath;
return 0;
}
static int audio_SetPath(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int ret = 0,path = 0;
unsigned long flags;
path = ucontrol->value.enumerated.item[0];
curpath = path;
#ifdef _USE_7520V3_PHONE_TYPE_C31F
switch (path) {
case 0:
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
mdelay(1);
gpio_set_value(ZX29_GPIO_40, GPIO_LOW);
break;
case 1:
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
mdelay(1);
raw_spin_lock_irqsave(&codec_pa_lock, flags);
gpio_set_value(ZX29_GPIO_39, GPIO_HIGH);
udelay(2);
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
udelay(2);
gpio_set_value(ZX29_GPIO_39, GPIO_HIGH);
raw_spin_unlock_irqrestore(&codec_pa_lock, flags);
gpio_set_value(ZX29_GPIO_40, GPIO_HIGH);
break;
case 2:
break;
case 3:
break;
default:
break;
}
#endif
return 0;
}
typedef enum
{
VP_PATH_HANDSET =0,
VP_PATH_SPEAKER,
VP_PATH_HEADSET,
VP_PATH_BLUETOOTH,
VP_PATH_BLUETOOTH_NO_NR,
VP_PATH_HSANDSPK,
VP_PATH_OFF = 255,
MAX_VP_PATH = VP_PATH_OFF
}T_ZDrv_VpPath;
extern int zDrvVp_Loop(T_ZDrv_VpPath path);
//#else
static const struct snd_kcontrol_new machine_snd_controls[] = {
SOC_SINGLE_BOOL_EXT("path stauts dump", 0,get_path_stauts_switch, set_path_stauts_switch),
};
//extern int rt5670_hs_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
int path_stauts_switch = 0;
static int set_path_stauts_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
struct snd_soc_dapm_path *p;
int path_stauts_switch = ucontrol->value.integer.value[0];
if (path_stauts_switch == 1)
{
list_for_each_entry(p, &card->paths, list){
//print_audio("Alsa path name (%s),longname (%s),sink (%s),source (%s),connect %d \n", p->name,p->long_name,p->sink->name,p->source->name,p->connect);
//printk("Alsa path longname %s,sink %s,source %s,connect %d \n", p->long_name,p->sink->name,p->source->name,p->connect);
}
}
return 0;
}
static int get_path_stauts_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = path_stauts_switch;
return 0;
};
#endif
#ifdef CONFIG_SND_SOC_JACK_DECTEC
static struct snd_soc_jack codec_headset;
/* Headset jack detection DAPM pins */
static struct snd_soc_jack_pin codec_headset_pins[] = {
{
.pin = "Headphone",
.mask = SND_JACK_HEADPHONE,
},
};
#endif
/* Started by AICoder, pid:53525s2951m0dfb1406409962017998611b17cc1 */
static int zx29startup(struct snd_pcm_substream *substream)
{
//int ret = 0;
print_audio("Alsa Entered func %s\n", __func__);
//CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: zx29_startup device=%d,stream=%d\n", substream->pcm->device, substream->stream);
struct snd_pcm *pcmC0D0p = snd_lookup_minor_data(16, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
struct snd_pcm *pcmC0D1p = snd_lookup_minor_data(17, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
struct snd_pcm *pcmC0D2p = snd_lookup_minor_data(18, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
struct snd_pcm *pcmC0D3p = snd_lookup_minor_data(19, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
//struct snd_pcm *pcmC0D4p = snd_lookup_minor_data(20, SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
struct snd_pcm *pcmC0D0c = snd_lookup_minor_data(24, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
struct snd_pcm *pcmC0D1c = snd_lookup_minor_data(25, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
struct snd_pcm *pcmC0D2c = snd_lookup_minor_data(26, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
struct snd_pcm *pcmC0D3c = snd_lookup_minor_data(27, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
//struct snd_pcm *pcmC0D4c = snd_lookup_minor_data(28, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
if ((pcmC0D0p == NULL) || (pcmC0D1p == NULL) || (pcmC0D2p == NULL) || (pcmC0D3p == NULL))
{
print_audio("Alsa Entered func %s, pcmC0D0p=%p, pcmC0D1p=%p, pcmC0D2p=%p, pcmC0D3p=%p\n", __func__,
pcmC0D0p, pcmC0D1p, pcmC0D2p, pcmC0D3p);
return -EINVAL;
}
if ((pcmC0D0p->streams[0].substream_opened && pcmC0D1p->streams[0].substream_opened) ||
(pcmC0D0p->streams[0].substream_opened && pcmC0D2p->streams[0].substream_opened) ||
(pcmC0D0p->streams[0].substream_opened && pcmC0D3p->streams[0].substream_opened) ||
(pcmC0D1p->streams[0].substream_opened && pcmC0D2p->streams[0].substream_opened) ||
(pcmC0D1p->streams[0].substream_opened && pcmC0D3p->streams[0].substream_opened) ||
(pcmC0D2p->streams[0].substream_opened && pcmC0D3p->streams[0].substream_opened))
{
print_audio("Alsa Entered func %s error busy, pcmC0D0p.opened=%d, pcmC0D1p.opened=%d, pcmC0D2p.opened=%d, pcmC0D3p.opened=%d\n",
__func__, pcmC0D0p->streams[0].substream_opened, pcmC0D1p->streams[0].substream_opened,
pcmC0D2p->streams[0].substream_opened, pcmC0D3p->streams[0].substream_opened);
sc_debug_info_record(MODULE_ID_CAP_AUDIO, "Alsa %s err, opened value pcmC0D0p=%d, pcmC0D1p=%d, pcmC0D2p=%d, pcmC0D3p=%d\n",
__func__, pcmC0D0p->streams[0].substream_opened, pcmC0D1p->streams[0].substream_opened,
pcmC0D2p->streams[0].substream_opened, pcmC0D3p->streams[0].substream_opened);
return -EBUSY;
//BUG();
}
if ((pcmC0D0c == NULL) || (pcmC0D1c == NULL) || (pcmC0D2c == NULL) || (pcmC0D3c == NULL))
{
print_audio("Alsa Entered func %s, pcmC0D0c=%p, pcmC0D1c=%p, pcmC0D2c=%p, pcmC0D3c=%p\n", __func__,
pcmC0D0c, pcmC0D1c, pcmC0D2c, pcmC0D3c);
return -EINVAL;
}
if ((pcmC0D0c->streams[1].substream_opened && pcmC0D1c->streams[1].substream_opened) ||
(pcmC0D0c->streams[1].substream_opened && pcmC0D2c->streams[1].substream_opened) ||
(pcmC0D0c->streams[1].substream_opened && pcmC0D3c->streams[1].substream_opened) ||
(pcmC0D1c->streams[1].substream_opened && pcmC0D2c->streams[1].substream_opened) ||
(pcmC0D1c->streams[1].substream_opened && pcmC0D3c->streams[1].substream_opened) ||
(pcmC0D2c->streams[1].substream_opened && pcmC0D3c->streams[1].substream_opened))
{
print_audio("Alsa Entered func %s error busy, pcmC0D0c.opened=%d, pcmC0D1c.opened=%d, pcmC0D2c.opened=%d,pcmC0D3c.opened=%d\n",
__func__, pcmC0D0c->streams[1].substream_opened, pcmC0D1c->streams[1].substream_opened,
pcmC0D2c->streams[1].substream_opened, pcmC0D3c->streams[1].substream_opened);
sc_debug_info_record(MODULE_ID_CAP_AUDIO, "Alsa %s err, opened value pcmC0D0c=%d, pcmC0D1c=%d, pcmC0D2c=%d, pcmC0D3c=%d\n",
__func__, pcmC0D0c->streams[1].substream_opened, pcmC0D1c->streams[1].substream_opened,
pcmC0D2c->streams[1].substream_opened, pcmC0D3c->streams[1].substream_opened);
return -EBUSY;
//BUG();
}
#if 0
unsigned long flags;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
gpio_set_value(ZX29_GPIO_125, GPIO_LOW);
mdelay(1);
raw_spin_lock_irqsave(&codec_pa_lock, flags);
gpio_set_value(ZX29_GPIO_125, GPIO_HIGH);
udelay(2);
gpio_set_value(ZX29_GPIO_125, GPIO_LOW);
udelay(2);
gpio_set_value(ZX29_GPIO_125, GPIO_HIGH);
udelay(2);
gpio_set_value(ZX29_GPIO_125, GPIO_LOW);
udelay(2);
gpio_set_value(ZX29_GPIO_125, GPIO_HIGH);
raw_spin_unlock_irqrestore(&codec_pa_lock, flags);
}
#endif
unsigned int armRegBit = 0;
//armRegBit = zx_read_reg(AON_WIFI_BT_CLK_CFG2);
//armRegBit &= 0xfffffffe;
//armRegBit |= 0x1;
//zx_write_reg(AON_WIFI_BT_CLK_CFG2, armRegBit);
return 0;
}
/* Ended by AICoder, pid:53525s2951m0dfb1406409962017998611b17cc1 */
static void zx29_shutdown(struct snd_pcm_substream *substream)
{
//CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: zx297520xx_shutdown device=%d, stream=%d\n", substream->pcm->device, substream->stream);
// print_audio("Alsa Entered func %s, stream=%d\n", __func__, substream->stream);
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
#ifdef _USE_7520V3_PHONE_TYPE_C31F
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
mdelay(1);
gpio_set_value(ZX29_GPIO_40, GPIO_LOW);
#endif
}
if (snd_soc_dai_active(cpu_dai))
return;
u32 armRegBit;
//armRegBit = zx_read_reg(AON_WIFI_BT_CLK_CFG2);
//armRegBit &= 0xfffffffe;
//armRegBit |= 0x0;
//zx_write_reg(AON_WIFI_BT_CLK_CFG2, armRegBit);
}
static void zx29_shutdown2(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
//CPPS_FUNC(cpps_callbacks, zDrv_Audio_Printf)("Alsa: zx29_shutdown2 device=%d, stream=%d\n", substream->pcm->device, substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
#ifdef _USE_7520V3_PHONE_TYPE_C31F
gpio_set_value(ZX29_GPIO_39, GPIO_LOW);
mdelay(1);
gpio_set_value(ZX29_GPIO_40, GPIO_LOW);
#endif
#ifdef USE_ALSA_VOICE_FUNC
//CPPS_FUNC(cpps_callbacks, zDrvVp_Loop)(VP_PATH_OFF);
#endif
}
if (snd_soc_dai_active(cpu_dai))
return;
u32 armRegBit;
//armRegBit = zx_read_reg(AON_WIFI_BT_CLK_CFG2);
//armRegBit &= 0xfffffffe;
//armRegBit |= 0x0;
//zx_write_reg(AON_WIFI_BT_CLK_CFG2, armRegBit);
}
static int zx29_init_paiftx(struct snd_soc_pcm_runtime *rtd)
{
//struct snd_soc_codec *codec = rtd->codec;
//struct snd_soc_dapm_context *dapm = &codec->dapm;
//snd_soc_dapm_enable_pin(dapm, "HPOL");
//snd_soc_dapm_enable_pin(dapm, "HPOR");
/* Other pins NC */
// snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
// print_audio("Alsa Entered func %s\n", __func__);
return 0;
}
static int zx29_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
print_audio("Alsa: Entered func %s\n", __func__);
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int ret;
int rfs = 0, frq_out = 0;
switch (params_rate(params)) {
case 8000:
case 16000:
case 11025:
case 22050:
case 24000:
case 32000:
case 44100:
case 48000:
rfs = 32;
break;
default:
{
ret = -EINVAL;
print_audio("Alsa: rate=%d not support,ret=%d!\n", params_rate(params),ret);
return ret;
}
}
frq_out = params_rate(params) * rfs * 2;
/* Set the Codec DAI configuration */
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){
print_audio("Alsa: codec dai snd_soc_dai_set_fmt fail,ret=%d!\n",ret);
return ret;
}
/* Set the AP DAI configuration */
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){
print_audio("Alsa: ap dai snd_soc_dai_set_fmt fail,ret=%d!\n",ret);
return ret;
}
/* Set the Codec DAI clk */
/*ret =snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_BCLK1,
fs*datawidth*2, 256*fs);
if (ret < 0){
print_audio("Alsa: codec dai clk snd_soc_dai_set_pll fail,ret=%d!\n",ret);
return ret;
}
*/
//ret = snd_soc_dai_set_sysclk(codec_dai, AK4940_CLKID_BCLK,ZXIC_MCLK, SND_SOC_CLOCK_IN);
//if (ret < 0){
// print_audio("Alsa: codec dai snd_soc_dai_set_sysclk fail,ret=%d!\n",ret);
// return ret;
// }
/* Set the AP DAI clk */
ret = snd_soc_dai_set_sysclk(cpu_dai, ZX29_I2S_WCLK_SEL,ZX29_I2S_WCLK_FREQ_122M88, SND_SOC_CLOCK_IN);
//ret = snd_soc_dai_set_sysclk(cpu_dai, ZX29_I2S_WCLK_SEL,ZX29_I2S_WCLK_FREQ_26M, SND_SOC_CLOCK_IN);
if (ret < 0){
print_audio("Alsa: cpu dai snd_soc_dai_set_sysclk fail,ret=%d!\n",ret);
return ret;
}
print_audio("Alsa: Entered func %s end\n", __func__);
return 0;
}
static int zx29_hw_params_lp(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
print_audio("Alsa: Entered func %s\n", __func__);
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int ret;
int rfs = 0, frq_out = 0;
switch (params_rate(params)) {
case 8000:
case 16000:
case 11025:
case 22050:
case 24000:
case 32000:
case 44100:
case 48000:
rfs = 32;
break;
default:
{
ret = -EINVAL;
print_audio("Alsa: rate=%d not support,ret=%d!\n", params_rate(params),ret);
return ret;
}
}
frq_out = params_rate(params) * rfs * 2;
/* Set the Codec DAI configuration */
/*
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){
print_audio("Alsa: codec dai snd_soc_dai_set_fmt fail,ret=%d!\n",ret);
return ret;
}
*/
/* Set the AP DAI configuration */
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){
print_audio("Alsa: ap dai snd_soc_dai_set_fmt fail,ret=%d!\n",ret);
return ret;
}
/* Set the Codec DAI clk */
/*ret =snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_BCLK1,
fs*datawidth*2, 256*fs);
if (ret < 0){
print_audio("Alsa: codec dai clk snd_soc_dai_set_pll fail,ret=%d!\n",ret);
return ret;
}
*/
/*
ret = snd_soc_dai_set_sysclk(codec_dai, ES8312_CLKID_MCLK,ZXIC_MCLK, SND_SOC_CLOCK_IN);
if (ret < 0){
print_audio("Alsa: codec dai snd_soc_dai_set_sysclk fail,ret=%d!\n",ret);
return ret;
}
*/
/* Set the AP DAI clk */
ret = snd_soc_dai_set_sysclk(cpu_dai, ZX29_I2S_WCLK_SEL,ZX29_I2S_WCLK_FREQ_26M, SND_SOC_CLOCK_IN);
if (ret < 0){
print_audio("Alsa: cpu dai snd_soc_dai_set_sysclk fail,ret=%d!\n",ret);
return ret;
}
print_audio("Alsa: Entered func %s end\n", __func__);
return 0;
}
static int zx29_hw_params_voice(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
print_audio("Alsa: Entered func %s\n", __func__);
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
int ret;
int rfs = 0, frq_out = 0;
switch (params_rate(params)) {
case 8000:
case 16000:
case 11025:
case 22050:
case 24000:
case 32000:
case 44100:
case 48000:
rfs = 32;
break;
default:
{
ret = -EINVAL;
print_audio("Alsa: rate=%d not support,ret=%d!\n", params_rate(params),ret);
return ret;
}
}
frq_out = params_rate(params) * rfs * 2;
/* Set the Codec DAI configuration */
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){
print_audio("Alsa: codec dai snd_soc_dai_set_fmt fail,ret=%d!\n",ret);
return ret;
}
/* Set the Codec DAI clk */
/*ret =snd_soc_dai_set_pll(codec_dai, 0, RT5670_PLL1_S_BCLK1,
fs*datawidth*2, 256*fs);
if (ret < 0){
print_audio("Alsa: codec dai clk snd_soc_dai_set_pll fail,ret=%d!\n",ret);
return ret;
}
ret = snd_soc_dai_set_sysclk(codec_dai, AK4940_CLKID_BCLK,ZXIC_MCLK, SND_SOC_CLOCK_IN);
if (ret < 0){
print_audio("Alsa: codec dai snd_soc_dai_set_sysclk fail,ret=%d!\n",ret);
return ret;
}
*/
print_audio("Alsa: Entered func %s end\n", __func__);
return 0;
}
int zx29_prepare2(struct snd_pcm_substream *substream)
{
int path, ret;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
//ret = CPPS_FUNC(cpps_callbacks, zDrvVp_Loop)(VP_PATH_SPEAKER);
if (ret < 0)
return -1;
}
return 0;
}
static void zx29_i2s_top_reg_cfg(void)
{
unsigned int i2s_top_reg;
int ret = 0;
#ifdef CONFIG_USE_PIN_I2S0
ret = gpio_request(PIN_I2S0_WS, "i2s0_ws");
if (ret < 0)
BUG();
ret = gpio_request(PIN_I2S0_CLK, "i2s0_clk");
if (ret < 0)
BUG();
ret = gpio_request(PIN_I2S0_DIN, "i2s0_din");
if (ret < 0)
BUG();
ret = gpio_request(PIN_I2S0_DOUT, "i2s0_dout");
if (ret < 0)
BUG();
zx29_gpio_config(PIN_I2S0_WS, FUN_I2S0_WS);
zx29_gpio_config(PIN_I2S0_CLK, FUN_I2S0_CLK);
zx29_gpio_config(PIN_I2S0_DIN, FUN_I2S0_DIN);
zx29_gpio_config(PIN_I2S0_DOUT, FUN_I2S0_DOUT);
//top i2s1 cfg
i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
i2s_top_reg &= 0xfffffff8;
i2s_top_reg |= 0x00000001; // inter arm_i2s1--top i2s1
zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
#elif defined (CONFIG_USE_PIN_I2S1)
ret = gpio_request(PIN_I2S1_WS,"i2s1_ws");
if(ret < 0)
BUG();
ret = gpio_request(PIN_I2S1_CLK,"i2s1_clk");
if(ret < 0)
BUG();
ret = gpio_request(PIN_I2S1_DIN,"i2s1_din");
if(ret < 0)
BUG();
ret = gpio_request(PIN_I2S1_DOUT,"i2s1_dout");
if(ret < 0)
BUG();
zx29_gpio_config(PIN_I2S1_WS, FUN_I2S1_WS);
zx29_gpio_config(PIN_I2S1_CLK, FUN_I2S1_CLK);
zx29_gpio_config(PIN_I2S1_DIN, FUN_I2S1_DIN);
zx29_gpio_config(PIN_I2S1_DOUT, FUN_I2S1_DOUT);
//top i2s2 cfg
i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
i2s_top_reg &= 0xfff8ffff;
i2s_top_reg |= 0x00010000; // inter arm_i2s1--top i2s2
zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
#endif
// inter loop
//i2s_top_reg = zx_read_reg(ZX29_I2S_LOOP_CFG);
//i2s_top_reg &= 0xfffffe07;
//i2s_top_reg |= 0x000000a8; // inter arm_i2s2--afe i2s
//zx_write_reg(ZX29_I2S_LOOP_CFG, i2s_top_reg);
// print_audio("Alsa %s i2s loop cfg reg=%x\n",__func__, zx_read_reg(ZX29_I2S_LOOP_CFG));
}
static int zx29_late_probe(struct snd_soc_card *card)
{
//struct snd_soc_codec *codec = card->rtd[0].codec;
//struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
int ret;
// print_audio("Alsa zx29_late_probe entry!\n");
#ifdef CONFIG_SND_SOC_JACK_DECTEC
ret = snd_soc_jack_new(codec, "Headset",
SND_JACK_HEADSET |SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
&codec_headset);
if (ret)
return ret;
ret = snd_soc_jack_add_pins(&codec_headset,
ARRAY_SIZE(codec_headset_pins),
codec_headset_pins);
if (ret)
return ret;
#ifdef CONFIG_SND_SOC_codec
//rt5670_hs_detect(codec, &codec_headset);
#endif
#endif
return 0;
}
static struct snd_soc_ops zx29_ops = {
//.startup = zx29_startup,
.shutdown = zx29_shutdown,
.hw_params = zx29_hw_params,
};
static struct snd_soc_ops zx29_ops_lp = {
//.startup = zx29_startup,
.shutdown = zx29_shutdown,
.hw_params = zx29_hw_params_lp,
};
static struct snd_soc_ops zx29_ops1 = {
//.startup = zx29_startup,
.shutdown = zx29_shutdown,
//.hw_params = zx29_hw_params1,
};
static struct snd_soc_ops zx29_ops2 = {
//.startup = zx29_startup,
.shutdown = zx29_shutdown2,
//.hw_params = zx29_hw_params1,
.prepare = zx29_prepare2,
};
static struct snd_soc_ops voice_ops = {
//.startup = zx29_startup,
//.shutdown = zx29_shutdown2,
.hw_params = zx29_hw_params_voice,
//.prepare = zx29_prepare2,
};
enum {
MERR_DPCM_AUDIO = 0,
MERR_DPCM_DEEP_BUFFER,
MERR_DPCM_COMPR,
};
#if 0
static struct snd_soc_card zxic_soc_card = {
.name = "zx298501_ak4940",
.owner = THIS_MODULE,
.dai_link = &zxic_dai_link,
.num_links = ARRAY_SIZE(zxic_dai_link),
#ifdef USE_ALSA_VOICE_FUNC
.controls = vp_snd_controls,
.num_controls = ARRAY_SIZE(vp_snd_controls),
#endif
// .late_probe = zx29_late_probe,
};
#endif
//static struct zx298501_ak4940_pdata *zx29_platform_data;
static int zx29_setup_pins(struct zx29_board_data *codec_pins, char *fun)
{
int ret;
//ret = gpio_request(codec_pins->codec_refclk, "codec_refclk");
if (ret < 0) {
printk(KERN_ERR "zx297520xx SoC Audio: %s pin already in use\n", fun);
return ret;
}
//zx29_gpio_config(codec_pins->codec_refclk, GPIO17_CLK_OUT2);
#ifdef _USE_7520V3_PHONE_TYPE_C31F
ret = gpio_request_one(ZX29_GPIO_39, GPIOF_OUT_INIT_LOW, "codec_pa");
if (ret < 0) {
printk(KERN_ERR "zx297520xx SoC Audio: codec_pa in use\n");
return ret;
}
ret = gpio_request_one(ZX29_GPIO_40, GPIOF_OUT_INIT_LOW, "codec_sw");
if (ret < 0) {
printk(KERN_ERR "zx297520xx SoC Audio: codec_sw in use\n");
return ret;
}
#endif
return 0;
}
#endif
static int zx29_remove(struct platform_device *pdev)
{
gpio_free(zx29_platform_data.codec_refclk);
platform_device_unregister(zx29_snd_device);
return 0;
}
#if 0
/*
* Default CFG switch settings to use this driver:
* ZX29
*/
/*
* Configure audio route as :-
* $ amixer sset 'DAC1' on,on
* $ amixer sset 'Right Headphone Mux' 'DAC'
* $ amixer sset 'Left Headphone Mux' 'DAC'
* $ amixer sset 'DAC1R Mixer AIF1.1' on
* $ amixer sset 'DAC1L Mixer AIF1.1' on
* $ amixer sset 'IN2L' on
* $ amixer sset 'IN2L PGA IN2LN' on
* $ amixer sset 'MIXINL IN2L' on
* $ amixer sset 'AIF1ADC1L Mixer ADC/DMIC' on
* $ amixer sset 'IN2R' on
* $ amixer sset 'IN2R PGA IN2RN' on
* $ amixer sset 'MIXINR IN2R' on
* $ amixer sset 'AIF1ADC1R Mixer ADC/DMIC' on
*/
/* ZX29 has a 16.934MHZ crystal attached to ak4940 */
#define ZX29_AK4940_FREQ 16934000
static int zx29_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int pll_out;
int ret;
/* AIF1CLK should be >=3MHz for optimal performance */
if (params_width(params) == 24)
pll_out = params_rate(params) * 384;
else if (params_rate(params) == 8000 || params_rate(params) == 11025)
pll_out = params_rate(params) * 512;
else
pll_out = params_rate(params) * 256;
ret = snd_soc_dai_set_pll(codec_dai, AK4940_FLL1, AK4940_FLL_SRC_MCLK1,
ZX29_AK4940_FREQ, pll_out);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_sysclk(codec_dai, AK4940_SYSCLK_FLL1,
pll_out, SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
return 0;
}
/*
* ZX29 AK4940 DAI operations.
*/
static struct snd_soc_ops zx29_ops = {
.hw_params = smdk_hw_params,
};
static int zx29_ak4940_init_paiftx(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dapm_context *dapm = &rtd->card->dapm;
/* Other pins NC */
snd_soc_dapm_nc_pin(dapm, "HPOUT2P");
snd_soc_dapm_nc_pin(dapm, "HPOUT2N");
snd_soc_dapm_nc_pin(dapm, "SPKOUTLN");
snd_soc_dapm_nc_pin(dapm, "SPKOUTLP");
snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
snd_soc_dapm_nc_pin(dapm, "SPKOUTRN");
snd_soc_dapm_nc_pin(dapm, "LINEOUT1N");
snd_soc_dapm_nc_pin(dapm, "LINEOUT1P");
snd_soc_dapm_nc_pin(dapm, "LINEOUT2N");
snd_soc_dapm_nc_pin(dapm, "LINEOUT2P");
snd_soc_dapm_nc_pin(dapm, "IN1LP");
snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
snd_soc_dapm_nc_pin(dapm, "IN1RP");
snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
return 0;
}
#endif
enum {
AUDIO_DL_MEDIA = 0,
AUDIO_DL_VOICE,
AUDIO_DL_2G_AND_3G_VOICE,
AUDIO_DL_VP_LOOP,
AUDIO_DL_3G_VOICE,
AUDIO_DL_MAX,
};
SND_SOC_DAILINK_DEF(dummy, \
DAILINK_COMP_ARRAY(COMP_DUMMY()));
//SND_SOC_DAILINK_DEF(cpu_i2s0, \
// DAILINK_COMP_ARRAY(COMP_CPU("media-cpu-dai")));
SND_SOC_DAILINK_DEF(cpu_i2s0, \
DAILINK_COMP_ARRAY(COMP_CPU("E1D02000.i2s")));
SND_SOC_DAILINK_DEF(voice_cpu, \
DAILINK_COMP_ARRAY(COMP_CPU("soc:voice_audio")));
SND_SOC_DAILINK_DEF(voice_2g_3g, \
DAILINK_COMP_ARRAY(COMP_CPU("voice_2g_3g-dai")));
SND_SOC_DAILINK_DEF(voice_3g, \
DAILINK_COMP_ARRAY(COMP_CPU("voice_3g-dai")));
//SND_SOC_DAILINK_DEF(ak4940, \
// DAILINK_COMP_ARRAY(COMP_CODEC("ak4940.1-0012", "ak4940-aif")));
SND_SOC_DAILINK_DEF(dummy_cpu, \
DAILINK_COMP_ARRAY(COMP_CPU("soc:zx29_snd_dummy")));
//SND_SOC_DAILINK_DEF(dummy_platform, \
// DAILINK_COMP_ARRAY(COMP_PLATFORM("soc:zx29_snd_dummy")));
SND_SOC_DAILINK_DEF(dummy_codec, \
DAILINK_COMP_ARRAY(COMP_CODEC("soc:zx29_snd_dummy", "zx29_snd_dummy_dai")));
SND_SOC_DAILINK_DEF(ti3100_codec, \
DAILINK_COMP_ARRAY(COMP_CODEC("tlv320aic31xx-codec.1-0012", "tlv320aic31xx-hifi")));
//SND_SOC_DAILINK_DEF(media_platform, \
// DAILINK_COMP_ARRAY(COMP_PLATFORM("zx29-pcm-audio")));
SND_SOC_DAILINK_DEF(media_platform, \
DAILINK_COMP_ARRAY(COMP_PLATFORM("E1D02000.i2s")));
//SND_SOC_DAILINK_DEF(voice_cpu, \
// DAILINK_COMP_ARRAY(COMP_CPU("E1D02000.i2s")));
SND_SOC_DAILINK_DEF(voice_platform, \
DAILINK_COMP_ARRAY(COMP_PLATFORM("soc:voice_audio")));
//static struct snd_soc_dai_link zx29_dai_link[] = {
struct snd_soc_dai_link zx29_dai_link[] = {
{
.name = "zx29_snd_dummy",//codec name
.stream_name = "zx29_snd_dumy",
//.nonatomic = true,
//.dynamic = 1,
//.dpcm_playback = 1,
.ops = &zx29_ops_lp,
.init = zx29_init_paiftx,
SND_SOC_DAILINK_REG(cpu_i2s0, dummy_codec, media_platform),
},
{
.name = "media",//codec name
.stream_name = "MultiMedia",
//.nonatomic = true,
//.dynamic = 1,
//.dpcm_playback = 1,
.ops = &zx29_ops,
.init = zx29_init_paiftx,
SND_SOC_DAILINK_REG(cpu_i2s0, dummy_codec, media_platform),
},
{
.name = "voice",//codec name
.stream_name = "voice",
//.nonatomic = true,
//.dynamic = 1,
//.dpcm_playback = 1,
.ops = &voice_ops,
//.init = zx29_init_paiftx,
SND_SOC_DAILINK_REG(voice_cpu, dummy_codec, voice_platform),
},
{
.name = "voice_2g3g_teak",//codec name
.stream_name = "voice_2g3g_teak",
//.nonatomic = true,
//.dynamic = 1,
//.dpcm_playback = 1,
.ops = &voice_ops,
//.init = zx29_init_paiftx,
SND_SOC_DAILINK_REG(voice_cpu, dummy_codec, voice_platform),
},
{
.name = "voice_3g",//codec name
.stream_name = "voice_3g",
//.nonatomic = true,
//.dynamic = 1,
//.dpcm_playback = 1,
.ops = &voice_ops,
//.init = zx29_init_paiftx,
SND_SOC_DAILINK_REG(voice_cpu, dummy_codec, voice_platform),
},
{
.name = "loop_test",//codec name
.stream_name = "loop_test",
//.nonatomic = true,
//.dynamic = 1,
//.dpcm_playback = 1,
.ops = &zx29_ops,
.init = zx29_init_paiftx,
SND_SOC_DAILINK_REG(cpu_i2s0, dummy_codec, dummy),
},
};
static struct snd_soc_card zx29_soc_card = {
.name = "zx29-sound-card",
.owner = THIS_MODULE,
.dai_link = zx29_dai_link,
.num_links = ARRAY_SIZE(zx29_dai_link),
#ifdef USE_ALSA_VOICE_FUNC
.controls = vp_snd_controls,
.num_controls = ARRAY_SIZE(vp_snd_controls),
#endif
};
static const struct of_device_id zx29_dummycodec_of_match[] = {
{ .compatible = "zxic,zx29_dummycodec", .data = &zx29_platform_data },
{},
};
MODULE_DEVICE_TABLE(of, zx29_dummycodec_of_match);
static void zx29_i2s_top_pin_cfg(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pinctrl *p;
struct pinctrl_state *s;
int ret = 0;
struct resource *res;
void __iomem *reg_base;
unsigned int val;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "soc_sys");
if (!res) {
dev_err(dev, "Reg region missing (%s)\n", "soc_sys");
//return -ENXIO;
}
#if 0
reg_base = devm_ioremap_resource(dev, res);
if (IS_ERR(reg_base )) {
dev_err(dev, "Reg region ioremap (%s) err=%li\n", "soc_sys",PTR_ERR(reg_base ));
//return PTR_ERR(reg_base );
}
#else
reg_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
#endif
//#if 1 //CONFIG_USE_PIN_I2S0
#ifdef CONFIG_USE_TOP_I2S0
dev_info(dev, "%s: arm i2s1 to top i2s0!!\n", __func__);
//9300
//top i2s1 cfg
val = zx_read_reg(reg_base+ZX29_I2S_TOP_LOOP_REG);
val &= ~(0x7<<0);
val |= 0x1<<0; // inter arm_i2s1--top i2s1
zx_write_reg(reg_base+ZX29_I2S_TOP_LOOP_REG, val);
#else //(CONFIG_USE_PIN_I2S1)
//8501evb
dev_info(dev, "%s: arm i2s1 to top i2s1!\n", __func__);
//top i2s2 cfg
val = zx_read_reg(reg_base+ZX29_I2S_TOP_LOOP_REG);
//val &= 0xfffffff8;
val &= ~(0x7<<16);
val |= 0x1<<16;// inter arm_i2s1--top i2s2
zx_write_reg(reg_base+ZX29_I2S_TOP_LOOP_REG, val);
#endif
p = devm_pinctrl_get(dev);
if (IS_ERR(p)) {
dev_err(dev, "%s: pinctrl get failure ,p=0x%llx,dev=0x%llx!!\n", __func__,p,dev);
return;
}
dev_info(dev, "%s: get pinctrl ,p=0x%llx,dev=0x%llx!!\n", __func__,p,dev);
s = pinctrl_lookup_state(p, "top_i2s");
if (IS_ERR(s)) {
devm_pinctrl_put(p);
dev_err(dev, " get state failure!!\n");
return;
}
ret = pinctrl_select_state(p, s);
if (ret < 0) {
devm_pinctrl_put(p);
dev_err(dev, " select state failure!!\n");
return;
}
dev_info(dev, "%s: set pinctrl end!\n", __func__);
}
static int zx29_audio_probe(struct platform_device *pdev)
{
int ret;
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &zx29_soc_card;
struct zx29_board_data *board;
const struct of_device_id *id;
enum of_gpio_flags flags;
unsigned int idx;
struct device *dev = &pdev->dev;
dev_info(&pdev->dev,"zx29_audio_probe start!\n");
card->dev = &pdev->dev;
board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
if (!board)
return -ENOMEM;
board->name = "zx29_dummycodec";
board->dev = &pdev->dev;
if (np) {
zx29_dai_link[0].cpus->dai_name = NULL;
zx29_dai_link[0].cpus->of_node = of_parse_phandle(np,
"zxic,i2s-controller", 0);
if (!zx29_dai_link[0].cpus->of_node) {
dev_err(&pdev->dev,
"Property 'zxic,i2s-controller' missing or invalid\n");
ret = -EINVAL;
}
zx29_dai_link[0].platforms->name = NULL;
zx29_dai_link[0].platforms->of_node = zx29_dai_link[0].cpus->of_node;
#if 0
zx29_dai_link[0].codecs->of_node = of_parse_phandle(np,
"zxic,audio-codec", 0);
if (!zx29_dai_link[0].codecs->of_node) {
dev_err(&pdev->dev,
"Property 'zxic,audio-codec' missing or invalid\n");
return -EINVAL;
}
#endif
}
id = of_match_device(of_match_ptr(zx29_dummycodec_of_match), &pdev->dev);
if (id)
*board = *((struct zx29_board_data *)id->data);
//platform_set_drvdata(pdev, board);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret){
dev_err(&pdev->dev, "snd_soc_register_card() failed:%d\n", ret);
return ret;
}
zx29_i2s_top_pin_cfg(pdev);
//codec_power_on(board,1);
dev_info(&pdev->dev,"zx29_audio_probe end!\n");
return ret;
}
static struct platform_driver zx29_platform_driver = {
.driver = {
.name = "zx29_dummycodec",
.of_match_table = of_match_ptr(zx29_dummycodec_of_match),
.pm = &snd_soc_pm_ops,
},
.probe = zx29_audio_probe,
//.remove = zx29_remove,
};
module_platform_driver(zx29_platform_driver);
MODULE_DESCRIPTION("zx29 ALSA SoC audio driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:zx29-audio-dummycodec");