aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xarch/arm/configs/herring_defconfig4
-rw-r--r--arch/arm/mach-s5pv210/clock.c4
-rw-r--r--arch/arm/mach-s5pv210/dev-audio.c2
-rwxr-xr-xarch/arm/mach-s5pv210/mach-herring.c3
-rw-r--r--arch/arm/mach-s5pv210/power-domain.c2
-rw-r--r--sound/soc/codecs/Kconfig3
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/wm8994.h265
-rw-r--r--sound/soc/codecs/wm8994_def.h5
-rwxr-xr-xsound/soc/codecs/wm8994_herring.c34
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.c320
-rwxr-xr-xsound/soc/codecs/wm8994_samsung.h8
-rw-r--r--sound/soc/samsung/Kconfig20
-rw-r--r--sound/soc/samsung/Makefile7
-rw-r--r--sound/soc/samsung/dma.c14
-rw-r--r--sound/soc/samsung/dma.h2
-rw-r--r--sound/soc/samsung/herring-wm8994.c20
-rw-r--r--sound/soc/samsung/i2s.c65
-rw-r--r--sound/soc/samsung/s3c-dma-wrapper.c118
-rw-r--r--sound/soc/samsung/s3c-dma.c11
-rw-r--r--sound/soc/samsung/s3c-dma.h2
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c359
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.h39
-rw-r--r--sound/soc/samsung/s3c-idma.c7
-rw-r--r--sound/soc/samsung/s3c-idma.h4
-rw-r--r--sound/soc/samsung/s5p-i2s_sec.c5
-rw-r--r--sound/soc/samsung/s5pc1xx-i2s.c355
-rw-r--r--sound/soc/samsung/s5pc1xx-i2s.h85
28 files changed, 1164 insertions, 601 deletions
diff --git a/arch/arm/configs/herring_defconfig b/arch/arm/configs/herring_defconfig
index 476f8ee..37d615c 100755
--- a/arch/arm/configs/herring_defconfig
+++ b/arch/arm/configs/herring_defconfig
@@ -222,8 +222,8 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
-CONFIG_SND_S3C24XX_SOC=y
-CONFIG_SND_S5P_WM8994=y
+CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_SAMSUNG_HERRING_WM8994=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index ae3aa2f..6d3e609 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -534,6 +534,7 @@ static struct clk init_clocks_off[] = {
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = S5P_CLKGATE_IP3_PCM2,
}, {
+#if 0
.name = "pcm",
.id = 1,
.parent = &clk_pclk_psys.clk,
@@ -546,6 +547,7 @@ static struct clk init_clocks_off[] = {
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = S5P_CLKGATE_IP3_PCM0,
}, {
+#endif
.name = "i2c-hdmiphy",
.id = -1,
.parent = &clk_pclk_psys.clk,
@@ -679,12 +681,14 @@ static struct clk init_clocks[] = {
.enable = s5pv210_clk_ip1_ctrl,
.ctrlbit = (1 << 26),
}, {
+#if 1
.name = "i2s_v50",
.id = 0,
.parent = &clk_p,
.enable = s5pv210_clk_ip3_ctrl,
.ctrlbit = S5P_CLKGATE_IP3_I2S0 | S5P_CLKGATE_IP3_PCM0,
}, {
+#endif
.name = "clk_out",
.id = -1,
.ops = &s5pc11x_clkout_ops,
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 0959bfe..c6109b1 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -80,7 +80,7 @@ static struct resource s5pv210_iis0_resource[] = {
};
struct platform_device s5pv210_device_iis0 = {
- .name = "s5pc1xx-iis",
+ .name = "samsung-i2s",
.id = 0,
.num_resources = ARRAY_SIZE(s5pv210_iis0_resource),
.resource = s5pv210_iis0_resource,
diff --git a/arch/arm/mach-s5pv210/mach-herring.c b/arch/arm/mach-s5pv210/mach-herring.c
index d54a949..f59484d 100755
--- a/arch/arm/mach-s5pv210/mach-herring.c
+++ b/arch/arm/mach-s5pv210/mach-herring.c
@@ -2731,7 +2731,7 @@ static struct i2c_board_info i2c_devs0[] __initdata = {
static struct i2c_board_info i2c_devs4[] __initdata = {
{
- I2C_BOARD_INFO("wm8994", (0x34>>1)),
+ I2C_BOARD_INFO("wm8994-samsung", (0x34>>1)),
.platform_data = &wm8994_pdata,
},
};
@@ -5473,6 +5473,7 @@ static struct platform_device *herring_devices[] __initdata = {
&sec_device_btsleep,
&ram_console_device,
&sec_device_wifi,
+ &samsung_asoc_dma,
};
unsigned int HWREV;
diff --git a/arch/arm/mach-s5pv210/power-domain.c b/arch/arm/mach-s5pv210/power-domain.c
index 0a10ef2..3383878 100644
--- a/arch/arm/mach-s5pv210/power-domain.c
+++ b/arch/arm/mach-s5pv210/power-domain.c
@@ -40,7 +40,7 @@ struct clk_should_be_running {
};
static struct regulator_consumer_supply s5pv210_pd_audio_supply[] = {
- REGULATOR_SUPPLY("pd", "s5pc1xx-iis.0"),
+ REGULATOR_SUPPLY("pd", "samsung-i2s.0"),
};
static struct regulator_consumer_supply s5pv210_pd_cam_supply[] = {
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 98175a0..abfd23b 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -356,6 +356,9 @@ config SND_SOC_WM8993
config SND_SOC_WM8994
tristate
+config SND_SOC_WM8994_SAMSUNG
+ tristate
+
config SND_SOC_WM8995
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fd85584..98bc006 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -74,6 +74,7 @@ snd-soc-wm8990-objs := wm8990.o
snd-soc-wm8991-objs := wm8991.o
snd-soc-wm8993-objs := wm8993.o
snd-soc-wm8994-objs := wm8994.o wm8994-tables.o wm8958-dsp2.o
+snd-soc-wm8994-samsung-objs := wm8994_samsung.o wm8994_herring.o
snd-soc-wm8995-objs := wm8995.o
snd-soc-wm9081-objs := wm9081.o
snd-soc-wm9705-objs := wm9705.o
@@ -166,6 +167,7 @@ obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o
obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
+obj-$(CONFIG_SND_SOC_WM8994_SAMSUNG) += snd-soc-wm8994-samsung.o
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 0a1db04..13257dc 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -1,145 +1,120 @@
-/*
- * wm8994.h -- WM8994 Soc Audio driver
- *
- * 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 _WM8994_H
-#define _WM8994_H
-
-#include <sound/soc.h>
-#include <linux/firmware.h>
-
-#include "wm_hubs.h"
-
-/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
-#define WM8994_SYSCLK_MCLK1 1
-#define WM8994_SYSCLK_MCLK2 2
-#define WM8994_SYSCLK_FLL1 3
-#define WM8994_SYSCLK_FLL2 4
-
-/* OPCLK is also configured with set_dai_sysclk, specify division*10 as rate. */
-#define WM8994_SYSCLK_OPCLK 5
-
-#define WM8994_FLL1 1
-#define WM8994_FLL2 2
-
-#define WM8994_FLL_SRC_MCLK1 1
-#define WM8994_FLL_SRC_MCLK2 2
-#define WM8994_FLL_SRC_LRCLK 3
-#define WM8994_FLL_SRC_BCLK 4
-
-typedef void (*wm8958_micdet_cb)(u16 status, void *data);
-
-int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt);
-int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- wm8958_micdet_cb cb, void *cb_data);
-
-#define WM8994_CACHE_SIZE 1570
-
-struct wm8994_access_mask {
- unsigned short readable; /* Mask of readable bits */
- unsigned short writable; /* Mask of writable bits */
-};
-
-extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE];
-extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
-
-int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event);
-
-void wm8958_dsp2_init(struct snd_soc_codec *codec);
-
-struct wm8994_micdet {
- struct snd_soc_jack *jack;
- int det;
- int shrt;
-};
-
-/* codec private data */
-struct wm8994_fll_config {
- int src;
- int in;
- int out;
-};
-
-#define WM8994_NUM_DRC 3
-#define WM8994_NUM_EQ 3
-
-struct wm8994_priv {
- struct wm_hubs_data hubs;
- enum snd_soc_control_type control_type;
- void *control_data;
- struct snd_soc_codec *codec;
- int sysclk[2];
- int sysclk_rate[2];
- int mclk[2];
- int aifclk[2];
- struct wm8994_fll_config fll[2], fll_suspend[2];
-
- int dac_rates[2];
- int lrclk_shared[2];
-
- int mbc_ena[3];
- int hpf1_ena[3];
- int hpf2_ena[3];
- int vss_ena[3];
- int enh_eq_ena[3];
-
- /* Platform dependant DRC configuration */
- const char **drc_texts;
- int drc_cfg[WM8994_NUM_DRC];
- struct soc_enum drc_enum;
-
- /* Platform dependant ReTune mobile configuration */
- int num_retune_mobile_texts;
- const char **retune_mobile_texts;
- int retune_mobile_cfg[WM8994_NUM_EQ];
- struct soc_enum retune_mobile_enum;
-
- /* Platform dependant MBC configuration */
- int mbc_cfg;
- const char **mbc_texts;
- struct soc_enum mbc_enum;
-
- /* Platform dependant VSS configuration */
- int vss_cfg;
- const char **vss_texts;
- struct soc_enum vss_enum;
-
- /* Platform dependant VSS HPF configuration */
- int vss_hpf_cfg;
- const char **vss_hpf_texts;
- struct soc_enum vss_hpf_enum;
-
- /* Platform dependant enhanced EQ configuration */
- int enh_eq_cfg;
- const char **enh_eq_texts;
- struct soc_enum enh_eq_enum;
-
- struct wm8994_micdet micdet[2];
-
- wm8958_micdet_cb jack_cb;
- void *jack_cb_data;
- int micdet_irq;
-
- int revision;
- struct wm8994_pdata *pdata;
-
- unsigned int aif1clk_enable:1;
- unsigned int aif2clk_enable:1;
-
- unsigned int aif1clk_disable:1;
- unsigned int aif2clk_disable:1;
-
- int dsp_active;
- const struct firmware *cur_fw;
- const struct firmware *mbc;
- const struct firmware *mbc_vss;
- const struct firmware *enh_eq;
-};
-
-#endif
+/*
+ * wm8994.h -- WM8994 Soc Audio driver
+ *
+ * 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 _WM8994_H
+#define _WM8994_H
+
+#include <sound/soc.h>
+
+extern struct snd_soc_codec_device soc_codec_dev_wm8994;
+// We don't use array - DW Shim.
+//extern struct snd_soc_dai wm8994_dai[];
+
+/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
+#define WM8994_SYSCLK_MCLK1 1
+#define WM8994_SYSCLK_MCLK2 2
+#define WM8994_SYSCLK_FLL1 3
+#define WM8994_SYSCLK_FLL2 4
+
+#define WM8994_FLL1 1
+#define WM8994_FLL2 2
+
+//-----------------------------------------------------------
+// Added belows codes by Samsung Electronics.
+
+#include "wm8994_def.h"
+
+extern struct snd_soc_dai wm8994_dai;
+
+#define WM8994_SYSCLK_MCLK 1
+#define WM8994_SYSCLK_FLL 2
+
+#define AUDIO_COMMON_DEBUG 0
+//#define WM8994_REGISTER_DUMP
+#if defined CONFIG_SND_SOC_WM8994_PCM
+#define ATTACH_ADDITINAL_PCM_DRIVER // for VT call.
+#endif
+//------------------------------------------------
+// Definitions of enum type
+//------------------------------------------------
+enum audio_path { OFF, RCV, SPK, HP, BT, SPK_HP};
+enum mic_path { MAIN, SUB, MIC_OFF};
+enum fmradio_audio_path { FMR_OFF, FMR_SPK, FMR_HP, FMR_SPK_MIX, FMR_HP_MIX, FMR_SPK_HP_MIX};
+enum call_state { DISCONNECT, CONNECT};
+enum power_state { CODEC_OFF, CODEC_ON };
+enum mic_state { MIC_NO_USE, MIC_USE};
+
+typedef void (*select_route)(struct snd_soc_codec *);
+typedef void (*select_mic_route)(struct snd_soc_codec *);
+
+struct wm8994_setup_data {
+ int i2c_bus;
+ unsigned short i2c_address;
+};
+
+struct wm8994_priv {
+ //u16 reg_cache[WM8994_REGISTER_COUNT];
+ struct snd_soc_codec codec;
+ int master;
+ int sysclk_source;
+ unsigned int mclk_rate;
+ unsigned int sysclk_rate;
+ unsigned int fs;
+ unsigned int bclk;
+ unsigned int hw_version; // For wolfson H/W version. 1 = Rev B, 3 = Rev D
+ enum audio_path cur_path;
+ enum mic_path rec_path;
+ enum fmradio_audio_path fmradio_path;
+ enum call_state call_state;
+ enum power_state power_state;
+ enum mic_state mic_state;
+ select_route *universal_playback_path;
+ select_route *universal_voicecall_path;
+ select_mic_route *universal_mic_path;
+ int testmode_config_flag; // for testmode.
+};
+
+#if AUDIO_COMMON_DEBUG
+#define DEBUG_LOG(format,...)\
+ printk ("[ "SUBJECT " (%s,%d) ] " format "\n", __func__, __LINE__, ## __VA_ARGS__);
+#else
+#define DEBUG_LOG(format,...)
+#endif
+
+#define DEBUG_LOG_ERR(format,...)\
+ printk (KERN_ERR "[ "SUBJECT " (%s,%d) ] " format "\n", __func__, __LINE__, ## __VA_ARGS__);
+
+// Definitions of function prototype.
+inline unsigned int wm8994_read(struct snd_soc_codec *codec,unsigned int reg);
+int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value);
+int audio_init(void);
+int audio_power(int en);
+void audio_ctrl_mic_bias_gpio(int enable);
+void wm8994_set_off(struct snd_soc_codec *codec);
+void wm8994_disable_playback_path(struct snd_soc_codec *codec, enum audio_path path);
+void wm8994_disable_fmradio_path(struct snd_soc_codec *codec, enum fmradio_audio_path path);
+void wm8994_disable_rec_path(struct snd_soc_codec *codec,enum mic_path rec_path);
+void wm8994_record_main_mic( struct snd_soc_codec *codec);
+void wm8994_record_headset_mic( struct snd_soc_codec *codec);
+void wm8994_set_playback_receiver(struct snd_soc_codec *codec);
+void wm8994_set_playback_headset(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker(struct snd_soc_codec *codec);
+void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_headset(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec);
+void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_headset(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_speaker(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_headset_mix(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_speaker_mix(struct snd_soc_codec *codec);
+void wm8994_set_fmradio_speaker_headset_mix(struct snd_soc_codec *codec);
+#if defined WM8994_REGISTER_DUMP
+void wm8994_register_dump(struct snd_soc_codec *codec);
+#endif
+#endif
diff --git a/sound/soc/codecs/wm8994_def.h b/sound/soc/codecs/wm8994_def.h
index 957d3f7..a375950 100644
--- a/sound/soc/codecs/wm8994_def.h
+++ b/sound/soc/codecs/wm8994_def.h
@@ -69,6 +69,10 @@
#define WM8994_DC_SERVO_ANA_1 0x5B
#define WM8994_DC_SERVO_ANA_2 0x5C
#define WM8994_ANALOGUE_HP_1 0x60
+#define WM8958_MIC_DETECT_1 0xD0
+#define WM8958_MIC_DETECT_2 0xD1
+#define WM8958_MIC_DETECT_3 0xD2
+#define WM8994_CHIP_REVISION 0x100
#define WM8994_CONTROL_INTERFACE 0x101
#define WM8994_WRITE_SEQUENCER_CTRL_1 0x110
#define WM8994_WRITE_SEQUENCER_CTRL_2 0x111
@@ -239,6 +243,7 @@
#define WM8994_INTERRUPT_CONTROL 0x740
#define WM8994_IRQ_DEBOUNCE 0x748
#define WM8994_IRQ_POLARITY 0x749
+#define WM8958_DSP2_EXECCONTROL 0xA0D
#define WM8994_WRITE_SEQUENCER_0 0x3000
#define WM8994_WRITE_SEQUENCER_1 0x3001
#define WM8994_WRITE_SEQUENCER_2 0x3002
diff --git a/sound/soc/codecs/wm8994_herring.c b/sound/soc/codecs/wm8994_herring.c
index bb67f85..6db5065 100755
--- a/sound/soc/codecs/wm8994_herring.c
+++ b/sound/soc/codecs/wm8994_herring.c
@@ -1121,7 +1121,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
/* S5P_SLEEP_CONFIG must be controlled by codec if codec use XUSBTI */
int wm8994_configure_clock(struct snd_soc_codec *codec, int en)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (en) {
clk_enable(wm8994->codec_clk);
@@ -1165,7 +1165,7 @@ static int wm8994_earsel_control(struct wm8994_platform_data *pdata, int en)
/* Audio Routing routines for the universal board..wm8994 codec*/
void wm8994_disable_path(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
enum audio_path path = wm8994->cur_path;
@@ -1330,7 +1330,7 @@ void wm8994_disable_path(struct snd_soc_codec *codec)
void wm8994_disable_rec_path(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
enum mic_path mic = wm8994->rec_path;
@@ -1514,7 +1514,7 @@ void wm8994_set_bluetooth_common_setting(struct snd_soc_codec *codec)
void wm8994_record_headset_mic(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
@@ -1627,7 +1627,7 @@ void wm8994_record_headset_mic(struct snd_soc_codec *codec)
void wm8994_record_main_mic(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
@@ -1894,7 +1894,7 @@ void wm8994_set_playback_receiver(struct snd_soc_codec *codec)
void wm8994_set_playback_headset(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
@@ -2077,7 +2077,7 @@ void wm8994_set_playback_headset(struct snd_soc_codec *codec)
void wm8994_set_playback_speaker(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
@@ -2185,7 +2185,7 @@ void wm8994_set_playback_speaker(struct snd_soc_codec *codec)
void wm8994_set_playback_speaker_headset(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
u16 val;
@@ -2595,7 +2595,7 @@ void wm8994_set_voicecall_common_setting(struct snd_soc_codec *codec)
static void wm8994_set_cdma_voicecall_receiver(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -2716,7 +2716,7 @@ static void wm8994_set_cdma_voicecall_receiver(struct snd_soc_codec *codec)
static void wm8994_set_gsm_voicecall_receiver(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -2818,7 +2818,7 @@ void wm8994_set_voicecall_receiver(struct snd_soc_codec *codec)
void wm8994_set_voicecall_headset(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -2983,7 +2983,7 @@ void wm8994_set_voicecall_headset(struct snd_soc_codec *codec)
void wm8994_set_voicecall_headphone(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -3140,7 +3140,7 @@ void wm8994_set_voicecall_headphone(struct snd_soc_codec *codec)
void wm8994_set_voicecall_speaker(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -3305,7 +3305,7 @@ void wm8994_set_voicecall_bluetooth(struct snd_soc_codec *codec)
void wm8994_set_voicecall_tty_vco(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -3462,7 +3462,7 @@ void wm8994_set_voicecall_tty_vco(struct snd_soc_codec *codec)
void wm8994_set_voicecall_tty_hco(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -3632,7 +3632,7 @@ void wm8994_set_voicecall_tty_hco(struct snd_soc_codec *codec)
void wm8994_set_voicecall_tty_full(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int val;
@@ -3792,7 +3792,7 @@ void wm8994_set_voicecall_tty_full(struct snd_soc_codec *codec)
int wm8994_set_codec_gain(struct snd_soc_codec *codec, u16 mode, u16 device)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int i;
u32 gain_set_bits = COMMON_SET_BIT;
u16 val;
diff --git a/sound/soc/codecs/wm8994_samsung.c b/sound/soc/codecs/wm8994_samsung.c
index 0fecae5..a9e569b 100755
--- a/sound/soc/codecs/wm8994_samsung.c
+++ b/sound/soc/codecs/wm8994_samsung.c
@@ -48,6 +48,8 @@
#define HDMI_USE_AUDIO
#endif
+//extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
+
/*
*Definitions of clock related.
*/
@@ -101,14 +103,14 @@ static struct {
{ 48, 9 },
};
-struct snd_soc_dai wm8994_dai;
-EXPORT_SYMBOL_GPL(wm8994_dai);
+//struct snd_soc_dai wm8994_dai;
+//EXPORT_SYMBOL_GPL(wm8994_dai);
-struct snd_soc_codec_device soc_codec_dev_pcm_wm8994;
-EXPORT_SYMBOL_GPL(soc_codec_dev_pcm_wm8994);
+//struct snd_soc_codec_device soc_codec_dev_pcm_wm8994;
+//EXPORT_SYMBOL_GPL(soc_codec_dev_pcm_wm8994);
-struct snd_soc_codec_device soc_codec_dev_wm8994;
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
+//struct snd_soc_codec_device soc_codec_dev_wm8994;
+//EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
/*
* Definitions of sound path
@@ -231,7 +233,7 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int reg = mc->reg;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("");
@@ -292,7 +294,7 @@ static int wm8994_get_mic_path(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8994->rec_path;
@@ -303,7 +305,7 @@ static int wm8994_set_mic_path(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("");
@@ -335,7 +337,7 @@ static int wm8994_get_path(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8994->cur_path;
@@ -346,7 +348,7 @@ static int wm8994_set_path(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
int val;
int path_num = ucontrol->value.integer.value[0];
@@ -412,7 +414,7 @@ static int wm8994_get_voice_path(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = wm8994->cur_path;
@@ -423,7 +425,7 @@ static int wm8994_set_voice_path(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct soc_enum *mc = (struct soc_enum *)kcontrol->private_value;
int path_num = ucontrol->value.integer.value[0];
@@ -473,7 +475,7 @@ static int wm8994_get_input_source(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("input_source_state = [%d]", wm8994->input_source);
@@ -484,7 +486,7 @@ static int wm8994_set_input_source(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int control_flag = ucontrol->value.integer.value[0];
@@ -569,16 +571,8 @@ static const struct snd_kcontrol_new wm8994_snd_controls[] = {
/* Add non-DAPM controls */
static int wm8994_add_controls(struct snd_soc_codec *codec)
{
- int err, i;
-
- for (i = 0; i < ARRAY_SIZE(wm8994_snd_controls); i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&wm8994_snd_controls[i],
- codec, NULL));
- if (err < 0)
- return err;
- }
- return 0;
+ return snd_soc_add_controls(codec, wm8994_snd_controls,
+ ARRAY_SIZE(wm8994_snd_controls));
}
static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
};
@@ -588,18 +582,18 @@ static const struct snd_soc_dapm_route audio_map[] = {
static int wm8994_add_widgets(struct snd_soc_codec *codec)
{
- snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
+ snd_soc_dapm_new_controls(&codec->dapm, wm8994_dapm_widgets,
ARRAY_SIZE(wm8994_dapm_widgets));
- snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+ snd_soc_dapm_add_routes(&codec->dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_new_widgets(codec);
+ snd_soc_dapm_new_widgets(&codec->dapm);
return 0;
}
static int configure_clock(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
unsigned int reg;
DEBUG_LOG("");
@@ -770,7 +764,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
- if (codec->bias_level == SND_SOC_BIAS_OFF) {
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
/* Bring up VMID with fast soft start */
snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
WM8994_STARTUP_BIAS_ENA |
@@ -810,7 +804,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
break;
}
- codec->bias_level = level;
+ codec->dapm.bias_level = level;
return 0;
}
@@ -819,7 +813,7 @@ static int wm8994_set_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("clk_id =%d ", clk_id);
@@ -843,7 +837,7 @@ static int wm8994_set_sysclk(struct snd_soc_dai *codec_dai,
static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
unsigned int aif1 = wm8994_read(codec, WM8994_AIF1_CONTROL_1);
unsigned int aif2 = wm8994_read(codec, WM8994_AIF1_MASTER_SLAVE);
@@ -945,7 +939,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int ret, i, best, best_val, cur_val;
unsigned int clocking1, clocking3, aif1, aif4, aif5;
@@ -1105,7 +1099,7 @@ static int wm8994_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
wm8994->stream_state |= PCM_STREAM_PLAYBACK;
@@ -1135,7 +1129,7 @@ static void wm8994_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *codec_dai)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("Stream_state = [0x%X], Codec State = [0x%X]",
wm8994->stream_state, wm8994->codec_state);
@@ -1179,7 +1173,7 @@ static void wm8994_shutdown(struct snd_pcm_substream *substream,
}
}
-static struct snd_soc_device *wm8994_socdev;
+//static struct snd_soc_device *wm8994_socdev;
static struct snd_soc_codec *wm8994_codec;
#define WM8994_RATES SNDRV_PCM_RATE_44100
@@ -1194,25 +1188,25 @@ static struct snd_soc_dai_ops wm8994_ops = {
.digital_mute = NULL,
};
-struct snd_soc_dai wm8994_dai = {
-
- .name = "WM8994 PAIFRX",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 6,
- .rates = WM8994_RATES,
- .formats = WM8994_FORMATS,
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = WM8994_RATES,
- .formats = WM8994_FORMATS,
- },
-
- .ops = &wm8994_ops,
+struct snd_soc_dai_driver wm8994_dai[] = {
+ {
+ .name = "WM8994 PAIFRX",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 1,
+ .channels_max = 6,
+ .rates = WM8994_RATES,
+ .formats = WM8994_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = WM8994_RATES,
+ .formats = WM8994_FORMATS,
+ },
+ .ops = &wm8994_ops,
+ },
};
/* gain_code range : integer 0~3 */
@@ -2827,7 +2821,7 @@ static const struct {
{ 0x03C3, 0x03C3 }, /* R1569 - Sidetone */
};
-static int wm8994_readable_register(unsigned int reg)
+static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
{
switch (reg) {
case WM8994_GPIO_1:
@@ -2853,6 +2847,27 @@ static int wm8994_readable_register(unsigned int reg)
return access_masks[reg].readable != 0;
}
+static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
+{
+ //if (reg >= WM8994_CACHE_SIZE)
+ // return 1;
+
+ switch (reg) {
+ case WM8994_SOFTWARE_RESET:
+ case WM8994_CHIP_REVISION:
+ case WM8994_DC_SERVO_1:
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_RATE_STATUS:
+ case WM8994_LDO_1:
+ case WM8994_LDO_2:
+ case WM8958_DSP2_EXECCONTROL:
+ case WM8958_MIC_DETECT_3:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/*
* initialise the WM8994 driver
* register the mixer and dsp interfaces with the kernel
@@ -2860,16 +2875,17 @@ static int wm8994_readable_register(unsigned int reg)
static int wm8994_init(struct wm8994_priv *wm8994_private,
struct wm8994_platform_data *pdata)
{
- struct snd_soc_codec *codec = &wm8994_private->codec;
+ struct snd_soc_codec *codec = wm8994_private->codec;
struct wm8994_priv *wm8994;
int ret = 0;
DEBUG_LOG("");
- codec->drvdata = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
- if (codec->drvdata == NULL)
+ wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
+ if (wm8994 == NULL)
return -ENOMEM;
- wm8994 = codec->drvdata;
+ snd_soc_codec_set_drvdata(codec, wm8994);
+#if 0
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
INIT_LIST_HEAD(&codec->dapm_paths);
@@ -2882,6 +2898,7 @@ static int wm8994_init(struct wm8994_priv *wm8994_private,
codec->set_bias_level = NULL;
codec->dai = &wm8994_dai;
codec->num_dai = 1;
+#endif
wm8994->universal_playback_path = universal_wm8994_playback_paths;
wm8994->universal_voicecall_path = universal_wm8994_voicecall_paths;
wm8994->universal_mic_path = universal_wm8994_mic_paths;
@@ -2910,15 +2927,17 @@ static int wm8994_init(struct wm8994_priv *wm8994_private,
wm8994->hw_version = wm8994_read(codec, 0x100);
- wm8994_socdev->card->codec = codec;
+ //wm8994_socdev->card->codec = codec;
wm8994_codec = codec;
+#if 0
ret = snd_soc_new_pcms(wm8994_socdev, SNDRV_DEFAULT_IDX1,
SNDRV_DEFAULT_STR1);
if (ret < 0) {
DEBUG_LOG_ERR("failed to create pcms\n");
goto pcm_err;
}
+#endif
wm8994_add_controls(codec);
wm8994_add_widgets(codec);
@@ -2926,8 +2945,8 @@ static int wm8994_init(struct wm8994_priv *wm8994_private,
return ret;
card_err:
- snd_soc_free_pcms(wm8994_socdev);
- snd_soc_dapm_free(wm8994_socdev);
+ //snd_soc_free_pcms(wm8994_socdev);
+ //snd_soc_dapm_free(wm8994_socdev);
pcm_err:
return ret;
@@ -2936,39 +2955,33 @@ pcm_err:
/* If the i2c layer weren't so broken, we could pass this kind of data
around */
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-
-static void *control_data1;
-
-static int wm8994_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec;
struct wm8994_priv *wm8994_priv;
int ret = -ENODEV;
struct wm8994_platform_data *pdata;
DEBUG_LOG("");
+ pr_info("WM8994 Audio Codec %s\n", WM8994_VERSION);
wm8994_priv = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
if (wm8994_priv == NULL)
return -ENOMEM;
- codec = &wm8994_priv->codec;
+ wm8994_priv->codec = codec;
#ifdef PM_DEBUG
pm_codec = codec;
#endif
- pdata = i2c->dev.platform_data;
+ pdata = dev_get_platdata(codec->dev);
if (!pdata) {
- dev_err(&i2c->dev, "failed to initialize WM8994\n");
+ dev_err(codec->dev, "failed to initialize WM8994\n");
goto err_bad_pdata;
}
if (!pdata->set_mic_bias) {
- dev_err(&i2c->dev, "bad pdata WM8994\n");
+ dev_err(codec->dev, "bad pdata WM8994\n");
goto err_bad_pdata;
}
@@ -3005,14 +3018,14 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
wm8994_ldo_control(pdata, 1);
codec->hw_write = (hw_write_t) i2c_master_send;
- i2c_set_clientdata(i2c, wm8994_priv);
- codec->control_data = i2c;
- codec->dev = &i2c->dev;
- control_data1 = i2c;
+ //i2c_set_clientdata(i2c, wm8994_priv);
+ //codec->control_data = i2c;
+ codec->control_data = to_i2c_client(codec->dev);
+ //codec->dev = &i2c->dev;
ret = wm8994_init(wm8994_priv, pdata);
if (ret) {
- dev_err(&i2c->dev, "failed to initialize WM8994\n");
+ dev_err(codec->dev, "failed to initialize WM8994\n");
goto err_init;
}
@@ -3028,9 +3041,9 @@ err_bad_pdata:
return ret;
}
-static int wm8994_i2c_remove(struct i2c_client *client)
+static int wm8994_codec_remove(struct snd_soc_codec *codec)
{
- struct wm8994_priv *wm8994_priv = i2c_get_clientdata(client);
+ struct wm8994_priv *wm8994_priv = snd_soc_codec_get_drvdata(codec);
gpio_free(wm8994_priv->pdata->ldo);
gpio_free(wm8994_priv->pdata->ear_sel);
@@ -3039,86 +3052,31 @@ static int wm8994_i2c_remove(struct i2c_client *client)
return 0;
}
-static const struct i2c_device_id wm8994_i2c_id[] = {
- {"wm8994", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
-
-static struct i2c_driver wm8994_i2c_driver = {
- .driver = {
- .name = "WM8994 I2C Codec",
- .owner = THIS_MODULE,
- },
- .probe = wm8994_i2c_probe,
- .remove = wm8994_i2c_remove,
- .id_table = wm8994_i2c_id,
-};
-
-static int wm8994_add_i2c_device(struct platform_device *pdev,
- const struct wm8994_setup_data *setup)
-{
- int ret;
-
- ret = i2c_add_driver(&wm8994_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8994_i2c_driver);
- return -ENODEV;
-}
-#endif
-
-static int wm8994_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8994_setup_data *setup;
-
- int ret = 0;
-
- pr_info("WM8994 Audio Codec %s\n", WM8994_VERSION);
-
- setup = socdev->codec_data;
- wm8994_socdev = socdev;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address)
- ret = wm8994_add_i2c_device(pdev, setup);
-#else
- /* Add other interfaces here */
-#endif
- return ret;
-}
-
+#if 0
/* power down chip */
static int wm8994_remove(struct platform_device *pdev)
{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ //struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = wm8994_codec;
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
+ //snd_soc_free_pcms(socdev);
+ //snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8994_i2c_driver);
#endif
- kfree(codec->drvdata);
+ //kfree(codec->drvdata);
return 0;
}
+#endif
#ifdef CONFIG_PM
-static int wm8994_suspend(struct platform_device *pdev, pm_message_t msg)
+static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- struct snd_soc_codec *codec = wm8994_codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("Codec State = [0x%X], Stream State = [0x%X]",
wm8994->codec_state, wm8994->stream_state);
@@ -3134,10 +3092,9 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t msg)
return 0;
}
-static int wm8994_resume(struct platform_device *pdev)
+static int wm8994_resume(struct snd_soc_codec *codec)
{
- struct snd_soc_codec *codec = wm8994_codec;
- struct wm8994_priv *wm8994 = codec->drvdata;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
DEBUG_LOG("%s..", __func__);
DEBUG_LOG_ERR("------WM8994 Revision = [%d]-------",
@@ -3152,6 +3109,7 @@ static int wm8994_resume(struct platform_device *pdev)
}
#endif
+#if 0
struct snd_soc_codec_device soc_codec_dev_wm8994 = {
.probe = wm8994_probe,
.remove = wm8994_remove,
@@ -3160,7 +3118,9 @@ struct snd_soc_codec_device soc_codec_dev_wm8994 = {
.resume = wm8994_resume,
#endif
};
+#endif
+#if 0
static int __init wm8994_modinit(void)
{
int ret;
@@ -3179,6 +3139,68 @@ static void __exit wm8994_exit(void)
}
module_exit(wm8994_exit);
+#endif
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
+ .probe = wm8994_codec_probe,
+ .remove = wm8994_codec_remove,
+ .suspend = wm8994_suspend,
+ .resume = wm8994_resume,
+ .read = wm8994_read,
+ .write = wm8994_write,
+ .readable_register = wm8994_readable,
+ .volatile_register = wm8994_volatile,
+ //.set_bias_level = wm8994_set_bias_level,
+
+ .reg_cache_size = WM8994_IRQ_POLARITY,
+ //.reg_cache_size = WM8994_CACHE_SIZE,
+ //.reg_cache_default = wm8994_reg_defaults,
+ .reg_word_size = 2,
+ .compress_type = SND_SOC_RBTREE_COMPRESSION,
+};
+
+static int wm8994_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return snd_soc_register_codec(&client->dev, &soc_codec_dev_wm8994,
+ wm8994_dai, ARRAY_SIZE(wm8994_dai));
+}
+
+static int wm8994_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+
+static const struct i2c_device_id wm8994_i2c_id[] = {
+ {"wm8994-samsung", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
+
+static struct i2c_driver wm8994_i2c_driver = {
+ .driver = {
+ .name = "wm8994-samsung-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8994_i2c_probe,
+ .remove = wm8994_i2c_remove,
+ .id_table = wm8994_i2c_id,
+};
+
+static __init int wm8994_driver_init(void)
+{
+ return i2c_add_driver(&wm8994_i2c_driver);
+}
+module_init(wm8994_driver_init);
+
+static __exit void wm8994_driver_exit(void)
+{
+ i2c_del_driver(&wm8994_i2c_driver);
+}
+module_exit(wm8994_driver_exit);
MODULE_DESCRIPTION("ASoC WM8994 driver");
MODULE_AUTHOR("Shaju Abraham shaju.abraham@samsung.com");
diff --git a/sound/soc/codecs/wm8994_samsung.h b/sound/soc/codecs/wm8994_samsung.h
index 0950b86..fa4fc3f 100755
--- a/sound/soc/codecs/wm8994_samsung.h
+++ b/sound/soc/codecs/wm8994_samsung.h
@@ -12,8 +12,6 @@
#include <sound/soc.h>
#include <linux/mfd/wm8994/wm8994_pdata.h>
-extern struct snd_soc_codec_device soc_codec_dev_wm8994;
-
/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
#define WM8994_SYSCLK_MCLK1 1
#define WM8994_SYSCLK_MCLK2 2
@@ -27,11 +25,11 @@ extern struct snd_soc_codec_device soc_codec_dev_wm8994;
#include "wm8994_def.h"
-extern struct snd_soc_dai wm8994_dai;
-
#define WM8994_SYSCLK_MCLK 1
#define WM8994_SYSCLK_FLL 2
+//#define WM8994_CACHE_SIZE 1570
+
#define AUDIO_COMMON_DEBUG 0
#define DEACTIVE 0x00
@@ -136,7 +134,7 @@ enum wm8994_dc_servo_slots {
};
struct wm8994_priv {
- struct snd_soc_codec codec;
+ struct snd_soc_codec *codec;
int master;
int sysclk_source;
unsigned int mclk_rate;
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index d155cbb..8601d70 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -20,6 +20,9 @@ config SND_S3C2412_SOC_I2S
select SND_S3C_I2SV2_SOC
select S3C2410_DMA
+config SND_S5PC1XX_I2S
+ tristate
+
config SND_SAMSUNG_PCM
tristate
@@ -34,6 +37,12 @@ config SND_SAMSUNG_SPDIF
config SND_SAMSUNG_I2S
tristate
+config S5P_INTERNAL_DMA
+ tristate
+
+config SND_S5P_WM8994_MASTER
+ bool
+
config SND_SOC_SAMSUNG_NEO1973_WM8753
tristate "Audio support for Openmoko Neo1973 Smartphones (GTA01/GTA02)"
depends on SND_SOC_SAMSUNG && (MACH_NEO1973_GTA01 || MACH_NEO1973_GTA02)
@@ -125,6 +134,17 @@ config SND_SOC_SAMSUNG_H1940_UDA1380
help
This driver provides audio support for HP iPAQ h1940 PDA.
+config SND_SOC_SAMSUNG_HERRING_WM8994
+ tristate "SoC I2S Audio support for HERRING - WM8994"
+ depends on SND_SOC_SAMSUNG && (MACH_HERRING)
+ select SND_S5PC1XX_I2S
+ select SND_SOC_WM8994_SAMSUNG
+ select S5P_INTERNAL_DMA
+ select SND_S5P_WM8994_MASTER
+ help
+ Say Y if you want to add support for SoC audio on herring
+ with the WM8994.
+
config SND_SOC_SAMSUNG_RX1950_UDA1380
tristate "Audio support for the HP iPAQ RX1950"
depends on SND_SOC_SAMSUNG && MACH_RX1950
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 683843a..98a007e 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -1,7 +1,8 @@
# S3c24XX Platform Support
-snd-soc-s3c24xx-objs := dma.o
+snd-soc-s3c24xx-objs := dma.o s3c-dma-wrapper.o
snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
+snd-soc-s5pc1xx-i2s-objs := s5pc1xx-i2s.o
snd-soc-ac97-objs := ac97.o
snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
snd-soc-samsung-spdif-objs := spdif.o
@@ -13,9 +14,11 @@ obj-$(CONFIG_SND_S3C24XX_I2S) += snd-soc-s3c24xx-i2s.o
obj-$(CONFIG_SND_SAMSUNG_AC97) += snd-soc-ac97.o
obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
+obj-$(CONFIG_SND_S5PC1XX_I2S) += snd-soc-s5pc1xx-i2s.o
obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o
obj-$(CONFIG_SND_SAMSUNG_PCM) += snd-soc-pcm.o
obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
+obj-$(CONFIG_S5P_INTERNAL_DMA) += s3c-idma.o s5p-i2s_sec.o
# S3C24XX Machine Support
snd-soc-jive-wm8750-objs := jive_wm8750.o
@@ -33,6 +36,7 @@ snd-soc-smdk-wm8994-objs := smdk_wm8994.o
snd-soc-smdk-wm9713-objs := smdk_wm9713.o
snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
snd-soc-goni-wm8994-objs := goni_wm8994.o
+snd-soc-herring-wm8994-objs := herring-wm8994.o
snd-soc-smdk-spdif-objs := smdk_spdif.o
snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
snd-soc-speyside-objs := speyside.o
@@ -46,6 +50,7 @@ obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC) += snd-soc-s3c24xx-simtec.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
obj-$(CONFIG_SND_SOC_SAMSUNG_H1940_UDA1380) += snd-soc-h1940-uda1380.o
+obj-$(CONFIG_SND_SOC_SAMSUNG_HERRING_WM8994) += snd-soc-herring-wm8994.o
obj-$(CONFIG_SND_SOC_SAMSUNG_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8580) += snd-soc-smdk-wm8580.o
obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 552bf43..fc56ed0 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -413,7 +413,11 @@ static void dma_free_dma_buffers(struct snd_pcm *pcm)
pr_debug("Entered %s\n", __func__);
+#ifdef CONFIG_S5P_INTERNAL_DMA
+ for (stream = 1; stream < 2; stream++) {
+#else
for (stream = 0; stream < 2; stream++) {
+#endif
substream = pcm->streams[stream].substream;
if (!substream)
continue;
@@ -442,13 +446,14 @@ static int dma_new(struct snd_card *card,
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = 0xffffffff;
+#ifndef CONFIG_S5P_INTERNAL_DMA
if (dai->driver->playback.channels_min) {
ret = preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
-
+#endif
if (dai->driver->capture.channels_min) {
ret = preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
@@ -459,11 +464,14 @@ out:
return ret;
}
-static struct snd_soc_platform_driver samsung_asoc_platform = {
+struct snd_soc_platform_driver samsung_asoc_platform = {
.ops = &dma_ops,
.pcm_new = dma_new,
.pcm_free = dma_free_dma_buffers,
};
+EXPORT_SYMBOL_GPL(samsung_asoc_platform);
+
+#ifndef CONFIG_S5P_INTERNAL_DMA
static int __devinit samsung_asoc_platform_probe(struct platform_device *pdev)
{
@@ -498,6 +506,8 @@ static void __exit samsung_asoc_exit(void)
}
module_exit(samsung_asoc_exit);
+#endif
+
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index c506592..2bb0d44 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -19,4 +19,6 @@ struct s3c_dma_params {
int dma_size; /* Size of the DMA transfer */
};
+extern struct snd_soc_platform_driver samsung_asoc_platform;
+
#endif
diff --git a/sound/soc/samsung/herring-wm8994.c b/sound/soc/samsung/herring-wm8994.c
index c4707e2..5f9dfe2 100644
--- a/sound/soc/samsung/herring-wm8994.c
+++ b/sound/soc/samsung/herring-wm8994.c
@@ -21,7 +21,7 @@
#include "../codecs/wm8994.h"
#include "s3c-dma.h"
#include "s5pc1xx-i2s.h"
-#include "s3c-i2s-v2.h"
+//#include "s3c-i2s-v2.h"
#include <linux/io.h>
@@ -42,8 +42,8 @@ int smdkc110_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 *cpu_dai = rtd->dai->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
int bfs, rfs, ret;
u32 ap_codec_clk;
#ifndef CONFIG_SND_S5P_WM8994_MASTER
@@ -290,20 +290,22 @@ static struct snd_soc_ops smdkc110_ops = {
/* digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link smdkc1xx_dai = {
- .name = "WM8994",
+ .name = "herring",
.stream_name = "WM8994 HiFi Playback",
- .cpu_dai = &s3c64xx_i2s_dai[I2S_NUM],
- .codec_dai = &wm8994_dai,
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "WM8994 PAIFRX",
+ .platform_name = "samsung-audio",
+ .codec_name = "wm8994-samsung-codec.4-001a",
.ops = &smdkc110_ops,
};
static struct snd_soc_card smdkc100 = {
.name = "smdkc110",
- .platform = &s3c_dma_wrapper,
.dai_link = &smdkc1xx_dai,
.num_links = 1,
};
+#if 0
static struct wm8994_setup_data smdkc110_wm8994_setup = {
/*
The I2C address of the WM89940 is 0x34. To the I2C driver
@@ -319,6 +321,7 @@ static struct snd_soc_device smdkc1xx_snd_devdata = {
.codec_dev = &soc_codec_dev_wm8994,
.codec_data = &smdkc110_wm8994_setup,
};
+#endif
static struct platform_device *smdkc1xx_snd_device;
static int __init smdkc110_audio_init(void)
@@ -331,8 +334,7 @@ static int __init smdkc110_audio_init(void)
if (!smdkc1xx_snd_device)
return -ENOMEM;
- platform_set_drvdata(smdkc1xx_snd_device, &smdkc1xx_snd_devdata);
- smdkc1xx_snd_devdata.dev = &smdkc1xx_snd_device->dev;
+ platform_set_drvdata(smdkc1xx_snd_device, &smdkc100);
ret = platform_device_add(smdkc1xx_snd_device);
if (ret)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 992a732..a779185 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/regulator/consumer.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -146,6 +147,8 @@ struct i2s_dai {
unsigned rfs, bfs;
/* I2S Controller's core clock */
struct clk *clk;
+ /* I2S Controller's power domain */
+ struct regulator *regulator;
/* Clock for generating I2S signals */
struct clk *op_clk;
/* Array of clock names for op_clk */
@@ -572,9 +575,13 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
unsigned int fmt)
{
struct i2s_dai *i2s = to_info(dai);
- u32 mod = readl(i2s->addr + I2SMOD);
+ u32 mod;
u32 tmp = 0;
+ dev_info(&i2s->pdev->dev, "base %p\n", i2s->addr);
+
+ mod = readl(i2s->addr + I2SMOD);
+
/* Format is priority */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J:
@@ -951,6 +958,9 @@ static int i2s_resume(struct snd_soc_dai *dai)
static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
{
+ struct clk *fout_epll, *mout_epll;
+ struct clk *mout_audss = NULL;
+ struct clk *sclk_audio, *iis_clk, *iis_busclk, *iis_ipclk; /* these belong shomewhere else */
struct i2s_dai *i2s = to_info(dai);
struct i2s_dai *other = i2s->pri_dai ? : i2s->sec_dai;
@@ -971,6 +981,59 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
}
clk_enable(i2s->clk);
+ /* Get i2s power domain regulator */
+ i2s->regulator = regulator_get(&i2s->pdev->dev, "pd");
+ if (IS_ERR(i2s->regulator)) {
+ dev_err(&i2s->pdev->dev, "%s: failed to get resource %s\n",
+ __func__, "i2s");
+ return PTR_ERR(i2s->regulator);
+ }
+
+ /* Enable Power domain */
+ regulator_enable(i2s->regulator);
+
+ fout_epll = clk_get(&i2s->pdev->dev, "fout_epll");
+ if (IS_ERR(fout_epll))
+ dev_err(&i2s->pdev->dev, "failed to get fout_epll\n");
+
+ mout_epll = clk_get(&i2s->pdev->dev, "mout_epll");
+ if (IS_ERR(mout_epll))
+ dev_err(&i2s->pdev->dev, "failed to get mout_epll\n");
+ clk_set_parent(mout_epll, fout_epll);
+
+ sclk_audio = clk_get(&i2s->pdev->dev, "sclk_audio");
+ if (IS_ERR(sclk_audio))
+ dev_err(&i2s->pdev->dev, "failed to get sclk_audio\n");
+ clk_set_parent(sclk_audio, mout_epll);
+
+ /* Need not to enable in general */
+ clk_enable(sclk_audio);
+
+ /* When I2S V5.1 used, initialize audio subsystem clock */
+ /* CLKMUX_ASS */
+ if (&i2s->pdev->id == 0) {
+ mout_audss = clk_get(NULL, "mout_audss");
+ if (IS_ERR(mout_audss))
+ dev_err(&i2s->pdev->dev, "failed to get mout_audss\n");
+ clk_set_parent(mout_audss, fout_epll);
+ /*MUX-I2SA*/
+ iis_clk = clk_get(&i2s->pdev->dev, "audio-bus");
+ if (IS_ERR(iis_clk))
+ dev_err(&i2s->pdev->dev, "failed to get audio-bus\n");
+ clk_set_parent(iis_clk, mout_audss);
+ /*getting AUDIO BUS CLK*/
+ iis_busclk = clk_get(NULL, "dout_audio_bus_clk_i2s");
+ if (IS_ERR(iis_busclk))
+ printk(KERN_ERR "failed to get audss_hclk\n");
+ iis_ipclk = clk_get(&i2s->pdev->dev, "i2s_v50");
+ if (IS_ERR(iis_ipclk))
+ dev_err(&i2s->pdev->dev, "failed to get i2s_v50_clock\n");
+ clk_enable(iis_ipclk);
+ clk_enable(iis_clk);
+ clk_enable(iis_busclk);
+ }
+
+
if (other) {
other->addr = i2s->addr;
other->clk = i2s->clk;
diff --git a/sound/soc/samsung/s3c-dma-wrapper.c b/sound/soc/samsung/s3c-dma-wrapper.c
index 8f371eb..2f87b68 100644
--- a/sound/soc/samsung/s3c-dma-wrapper.c
+++ b/sound/soc/samsung/s3c-dma-wrapper.c
@@ -11,125 +11,125 @@
*/
#include <sound/soc.h>
-#include "s3c-dma.h"
+#include "dma.h"
#include "s3c-idma.h"
static int s3c_wrpdma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->hw_params)
- return platform->pcm_ops->hw_params(substream, params);
+ if (platform->ops->hw_params)
+ return platform->ops->hw_params(substream, params);
else
return 0;
}
static int s3c_wrpdma_hw_free(struct snd_pcm_substream *substream)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->hw_free)
- return platform->pcm_ops->hw_free(substream);
+ if (platform->ops->hw_free)
+ return platform->ops->hw_free(substream);
else
return 0;
}
static int s3c_wrpdma_prepare(struct snd_pcm_substream *substream)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->prepare)
- return platform->pcm_ops->prepare(substream);
+ if (platform->ops->prepare)
+ return platform->ops->prepare(substream);
else
return 0;
}
static int s3c_wrpdma_trigger(struct snd_pcm_substream *substream, int cmd)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->trigger)
- return platform->pcm_ops->trigger(substream, cmd);
+ if (platform->ops->trigger)
+ return platform->ops->trigger(substream, cmd);
else
return 0;
}
static snd_pcm_uframes_t s3c_wrpdma_pointer(struct snd_pcm_substream *substream)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->pointer)
- return platform->pcm_ops->pointer(substream);
+ if (platform->ops->pointer)
+ return platform->ops->pointer(substream);
else
return 0;
}
static int s3c_wrpdma_open(struct snd_pcm_substream *substream)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->open)
- return platform->pcm_ops->open(substream);
+ if (platform->ops->open)
+ return platform->ops->open(substream);
else
return 0;
}
static int s3c_wrpdma_close(struct snd_pcm_substream *substream)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->close)
- return platform->pcm_ops->close(substream);
+ if (platform->ops->close)
+ return platform->ops->close(substream);
else
return 0;
}
@@ -137,17 +137,17 @@ static int s3c_wrpdma_close(struct snd_pcm_substream *substream)
static int s3c_wrpdma_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->ioctl)
- return platform->pcm_ops->ioctl(substream, cmd, arg);
+ if (platform->ops->ioctl)
+ return platform->ops->ioctl(substream, cmd, arg);
else
return 0;
}
@@ -155,17 +155,17 @@ static int s3c_wrpdma_ioctl(struct snd_pcm_substream *substream,
static int s3c_wrpdma_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
- struct snd_soc_platform *platform;
+ struct snd_soc_platform_driver *platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
platform = &idma_soc_platform;
else
#endif
- platform = &s3c24xx_soc_platform;
+ platform = &samsung_asoc_platform;
- if (platform->pcm_ops->mmap)
- return platform->pcm_ops->mmap(substream, vma);
+ if (platform->ops->mmap)
+ return platform->ops->mmap(substream, vma);
else
return 0;
}
@@ -184,9 +184,9 @@ static struct snd_pcm_ops s3c_wrpdma_ops = {
static void s3c_wrpdma_pcm_free(struct snd_pcm *pcm)
{
- struct snd_soc_platform *gdma_platform;
+ struct snd_soc_platform_driver *gdma_platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
- struct snd_soc_platform *idma_platform;
+ struct snd_soc_platform_driver *idma_platform;
#endif
#ifdef CONFIG_S5P_INTERNAL_DMA
@@ -194,7 +194,7 @@ static void s3c_wrpdma_pcm_free(struct snd_pcm *pcm)
if (idma_platform->pcm_free)
idma_platform->pcm_free(pcm);
#endif
- gdma_platform = &s3c24xx_soc_platform;
+ gdma_platform = &samsung_asoc_platform;
if (gdma_platform->pcm_free)
gdma_platform->pcm_free(pcm);
}
@@ -202,9 +202,9 @@ static void s3c_wrpdma_pcm_free(struct snd_pcm *pcm)
static int s3c_wrpdma_pcm_new(struct snd_card *card,
struct snd_soc_dai *dai, struct snd_pcm *pcm)
{
- struct snd_soc_platform *gdma_platform;
+ struct snd_soc_platform_driver *gdma_platform;
#ifdef CONFIG_S5P_INTERNAL_DMA
- struct snd_soc_platform *idma_platform;
+ struct snd_soc_platform_driver *idma_platform;
#endif
/* sec_fifo i/f always use internal h/w buffers
@@ -215,30 +215,50 @@ static int s3c_wrpdma_pcm_new(struct snd_card *card,
if (idma_platform->pcm_new)
idma_platform->pcm_new(card, dai, pcm);
#endif
- gdma_platform = &s3c24xx_soc_platform;
+ gdma_platform = &samsung_asoc_platform;
if (gdma_platform->pcm_new)
gdma_platform->pcm_new(card, dai, pcm);
return 0;
}
-struct snd_soc_platform s3c_dma_wrapper = {
- .name = "samsung-audio",
- .pcm_ops = &s3c_wrpdma_ops,
+static struct snd_soc_platform_driver s3c_dma_wrapper = {
+ .ops = &s3c_wrpdma_ops,
.pcm_new = s3c_wrpdma_pcm_new,
.pcm_free = s3c_wrpdma_pcm_free,
};
-EXPORT_SYMBOL_GPL(s3c_dma_wrapper);
+//EXPORT_SYMBOL_GPL(s3c_dma_wrapper);
+
+static int __devinit s3c_dma_wrapper_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_platform(&pdev->dev, &s3c_dma_wrapper);
+}
+
+static int __devexit s3c_dma_wrapper_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver s3c_dma_wrapper_driver = {
+ .driver = {
+ .name = "samsung-audio",
+ .owner = THIS_MODULE,
+ },
+
+ .probe = s3c_dma_wrapper_platform_probe,
+ .remove = __devexit_p(s3c_dma_wrapper_platform_remove),
+};
static int __init s3c_dma_wrapper_init(void)
{
- return snd_soc_register_platform(&s3c_dma_wrapper);
+ return platform_driver_register(&s3c_dma_wrapper_driver);
}
module_init(s3c_dma_wrapper_init);
static void __exit s3c_dma_wrapper_exit(void)
{
- snd_soc_unregister_platform(&s3c_dma_wrapper);
+ platform_driver_unregister(&s3c_dma_wrapper_driver);
}
module_exit(s3c_dma_wrapper_exit);
diff --git a/sound/soc/samsung/s3c-dma.c b/sound/soc/samsung/s3c-dma.c
index 765cea1..8985964 100644
--- a/sound/soc/samsung/s3c-dma.c
+++ b/sound/soc/samsung/s3c-dma.c
@@ -147,7 +147,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned long totbytes = params_buffer_bytes(params);
struct s3c_dma_params *dma =
- snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream);
+ snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
int ret = 0;
@@ -449,14 +449,14 @@ static int s3c_dma_new(struct snd_card *card,
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = 0xffffffff;
#ifndef CONFIG_S5P_INTERNAL_DMA
- if (dai->playback.channels_min) {
+ if (dai->driver->playback.channels_min) {
ret = s3c_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
#endif
- if (dai->capture.channels_min) {
+ if (dai->driver->capture.channels_min) {
ret = s3c_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -466,9 +466,8 @@ static int s3c_dma_new(struct snd_card *card,
return ret;
}
-struct snd_soc_platform s3c24xx_soc_platform = {
- .name = "s3c24xx-audio",
- .pcm_ops = &s3c_dma_ops,
+struct snd_soc_platform_driver s3c24xx_soc_platform = {
+ .ops = &s3c_dma_ops,
.pcm_new = s3c_dma_new,
.pcm_free = s3c_dma_free_dma_buffers,
};
diff --git a/sound/soc/samsung/s3c-dma.h b/sound/soc/samsung/s3c-dma.h
index d2bed08..cb869db 100644
--- a/sound/soc/samsung/s3c-dma.h
+++ b/sound/soc/samsung/s3c-dma.h
@@ -26,7 +26,7 @@ struct s3c_dma_params {
//#define pr_debug(fmt...) printk(fmt)
/* platform data */
-extern struct snd_soc_platform s3c24xx_soc_platform;
+extern struct snd_soc_platform_driver s3c24xx_soc_platform;
extern struct snd_soc_platform s3c24xx_pcm_soc_platform;
extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 5179b73..52074a2b 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -1,4 +1,4 @@
-/* sound/soc/s3c24xx/s3c-i2c-v2.c
+/* sound/soc/samsung/s3c-i2c-v2.c
*
* ALSA Soc Audio Layer - I2S core for newer Samsung SoCs.
*
@@ -16,34 +16,27 @@
* option) any later version.
*/
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
#include <linux/delay.h>
#include <linux/clk.h>
-#include <linux/kernel.h>
#include <linux/io.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
#include <sound/soc.h>
-
-#include <plat/regs-iis.h>
+#include <sound/pcm_params.h>
#include <mach/dma.h>
+#include "regs-i2s-v2.h"
#include "s3c-i2s-v2.h"
-#include "s3c-dma.h"
+#include "dma.h"
#undef S3C_IIS_V2_SUPPORTED
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) \
+ || defined(CONFIG_CPU_S5PV210)
#define S3C_IIS_V2_SUPPORTED
#endif
-#if defined(CONFIG_PLAT_S3C64XX) || defined(CONFIG_PLAT_S5P)
+#ifdef CONFIG_PLAT_S3C64XX
#define S3C_IIS_V2_SUPPORTED
#endif
@@ -55,7 +48,7 @@
static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
{
- return cpu_dai->private_data;
+ return snd_soc_dai_get_drvdata(cpu_dai);
}
#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
@@ -133,12 +126,8 @@ static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
*/
con |= S3C2412_IISCON_TXDMA_PAUSE;
- con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
- if (con & S5P_IISCON_TXSDMACTIVE) { /* If sec is active */
- writel(con, regs + S3C2412_IISCON);
- return;
- }
con |= S3C2412_IISCON_TXCH_PAUSE;
+ con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
switch (mod & S3C2412_IISMOD_MODE_MASK) {
case S3C2412_IISMOD_MODE_TXRX:
@@ -276,35 +265,14 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
iismod = readl(i2s->regs + S3C2412_IISMOD);
pr_debug("hw_params r: IISMOD: %x \n", iismod);
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
-#define IISMOD_MASTER_MASK S3C2412_IISMOD_MASTER_MASK
-#define IISMOD_SLAVE S3C2412_IISMOD_SLAVE
-#define IISMOD_MASTER S3C2412_IISMOD_MASTER_INTERNAL
-#endif
-
-#if defined(CONFIG_PLAT_S3C64XX) || defined(CONFIG_PLAT_S5P)
-/* From Rev1.1 datasheet, we have two master and two slave modes:
- * IMS[11:10]:
- * 00 = master mode, fed from PCLK
- * 01 = master mode, fed from CLKAUDIO
- * 10 = slave mode, using PCLK
- * 11 = slave mode, using I2SCLK
- */
-#define IISMOD_MASTER_MASK (1 << 11)
-#define IISMOD_SLAVE (1 << 11)
-#define IISMOD_MASTER (0 << 11)
-#endif
-
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
i2s->master = 0;
- iismod &= ~IISMOD_MASTER_MASK;
- iismod |= IISMOD_SLAVE;
+ iismod |= S3C2412_IISMOD_SLAVE;
break;
case SND_SOC_DAIFMT_CBS_CFS:
i2s->master = 1;
- iismod &= ~IISMOD_MASTER_MASK;
- iismod |= IISMOD_MASTER;
+ iismod &= ~S3C2412_IISMOD_SLAVE;
break;
default:
pr_err("unknwon master/slave format\n");
@@ -336,91 +304,114 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
return 0;
}
-int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
+static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
- struct snd_soc_dai *socdai)
+ struct snd_soc_dai *dai)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai_link *dai = rtd->dai;
- struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ struct s3c_dma_params *dma_data;
u32 iismod;
pr_debug("Entered %s\n", __func__);
-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream,i2s->dma_playback);
+ dma_data = i2s->dma_playback;
else
- snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream,i2s->dma_capture);
+ dma_data = i2s->dma_capture;
+
+ snd_soc_dai_set_dma_data(dai, substream, dma_data);
/* Working copies of register */
iismod = readl(i2s->regs + S3C2412_IISMOD);
pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
- switch(params_channels(params)){
- case 1:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- i2s->dma_playback->dma_size = 2;
- else
- i2s->dma_capture->dma_size = 2;
- break;
- case 2:
- break;
- default:
- break;
- }
-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+ iismod &= ~S3C64XX_IISMOD_BLC_MASK;
+ /* Sample size */
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
- iismod |= S3C2412_IISMOD_8BIT;
+ iismod |= S3C64XX_IISMOD_BLC_8BIT;
break;
case SNDRV_PCM_FORMAT_S16_LE:
- iismod &= ~S3C2412_IISMOD_8BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iismod |= S3C64XX_IISMOD_BLC_24BIT;
break;
}
-#endif
-#if defined(CONFIG_PLAT_S3C64XX) || defined(CONFIG_PLAT_S5P)
- iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
- /* Sample size */
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- /* 8 bit sample, 16fs BCLK */
- iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
+
+ return 0;
+}
+
+static int s3c_i2sv2_set_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+ u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+ pr_debug("Entered %s\n", __func__);
+ pr_debug("%s r: IISMOD: %x\n", __func__, iismod);
+
+ switch (clk_id) {
+ case S3C_I2SV2_CLKSRC_PCLK:
+ iismod &= ~S3C2412_IISMOD_IMS_SYSMUX;
break;
- case SNDRV_PCM_FORMAT_S16_LE:
- /* 16 bit sample, 32fs BCLK */
+
+ case S3C_I2SV2_CLKSRC_AUDIOBUS:
+ iismod |= S3C2412_IISMOD_IMS_SYSMUX;
break;
- case SNDRV_PCM_FORMAT_S24_LE:
- /* 24 bit sample, 48fs BCLK */
- iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
+
+ case S3C_I2SV2_CLKSRC_CDCLK:
+ /* Error if controller doesn't have the CDCLKCON bit */
+ if (!(i2s->feature & S3C_FEATURE_CDCLKCON))
+ return -EINVAL;
+
+ switch (dir) {
+ case SND_SOC_CLOCK_IN:
+ iismod |= S3C64XX_IISMOD_CDCLKCON;
+ break;
+ case SND_SOC_CLOCK_OUT:
+ iismod &= ~S3C64XX_IISMOD_CDCLKCON;
+ break;
+ default:
+ return -EINVAL;
+ }
break;
- }
- /* Set the IISMOD[25:24](BLC_P) to same value */
- iismod &= ~(S5P_IISMOD_BLCPMASK);
- iismod |= ((iismod & S3C64XX_IISMOD_BLC_MASK) << 11);
-#endif
+ default:
+ return -EINVAL;
+ }
writel(iismod, i2s->regs + S3C2412_IISMOD);
- pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
+ pr_debug("%s w: IISMOD: %x\n", __func__, iismod);
+
return 0;
}
-EXPORT_SYMBOL_GPL(s3c2412_i2s_hw_params);
-int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai);
+ struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai);
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
unsigned long irqs;
int ret = 0;
+ struct s3c_dma_params *dma_data =
+ snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
pr_debug("Entered %s\n", __func__);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
+ /* On start, ensure that the FIFOs are cleared and reset. */
+
+ writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
+ i2s->regs + S3C2412_IISFIC);
+
+ /* clear again, just in case */
+ writel(0x0, i2s->regs + S3C2412_IISFIC);
+
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (!i2s->master) {
@@ -437,6 +428,14 @@ int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
s3c2412_snd_txctrl(i2s, 1);
local_irq_restore(irqs);
+
+ /*
+ * Load the next buffer to DMA to meet the reqirement
+ * of the auto reload mechanism of S3C24XX.
+ * This call won't bother S3C64XX.
+ */
+ s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+
break;
case SNDRV_PCM_TRIGGER_STOP:
@@ -459,7 +458,6 @@ int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
exit_err:
return ret;
}
-EXPORT_SYMBOL_GPL(s3c2412_i2s_trigger);
/*
* Set S3C2412 Clock dividers
@@ -474,29 +472,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
switch (div_id) {
case S3C_I2SV2_DIV_BCLK:
- if (div > 3) {
- /* convert value to bit field */
-
- switch (div) {
- case 16:
- div = S3C2412_IISMOD_BCLK_16FS;
- break;
+ switch (div) {
+ case 16:
+ div = S3C2412_IISMOD_BCLK_16FS;
+ break;
- case 32:
- div = S3C2412_IISMOD_BCLK_32FS;
- break;
+ case 32:
+ div = S3C2412_IISMOD_BCLK_32FS;
+ break;
- case 24:
- div = S3C2412_IISMOD_BCLK_24FS;
- break;
+ case 24:
+ div = S3C2412_IISMOD_BCLK_24FS;
+ break;
- case 48:
- div = S3C2412_IISMOD_BCLK_48FS;
- break;
+ case 48:
+ div = S3C2412_IISMOD_BCLK_48FS;
+ break;
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
}
reg = readl(i2s->regs + S3C2412_IISMOD);
@@ -507,29 +501,25 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
break;
case S3C_I2SV2_DIV_RCLK:
- if (div > 3) {
- /* convert value to bit field */
-
- switch (div) {
- case 256:
- div = S3C2412_IISMOD_RCLK_256FS;
- break;
+ switch (div) {
+ case 256:
+ div = S3C2412_IISMOD_RCLK_256FS;
+ break;
- case 384:
- div = S3C2412_IISMOD_RCLK_384FS;
- break;
+ case 384:
+ div = S3C2412_IISMOD_RCLK_384FS;
+ break;
- case 512:
- div = S3C2412_IISMOD_RCLK_512FS;
- break;
+ case 512:
+ div = S3C2412_IISMOD_RCLK_512FS;
+ break;
- case 768:
- div = S3C2412_IISMOD_RCLK_768FS;
- break;
+ case 768:
+ div = S3C2412_IISMOD_RCLK_768FS;
+ break;
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
}
reg = readl(i2s->regs + S3C2412_IISMOD);
@@ -555,6 +545,33 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
return 0;
}
+static snd_pcm_sframes_t s3c2412_i2s_delay(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ u32 reg = readl(i2s->regs + S3C2412_IISFIC);
+ snd_pcm_sframes_t delay;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ delay = S3C2412_IISFIC_TXCOUNT(reg);
+ else
+ delay = S3C2412_IISFIC_RXCOUNT(reg);
+
+ return delay;
+}
+
+struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
+ u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
+
+ if (iismod & S3C2412_IISMOD_IMS_SYSMUX)
+ return i2s->iis_cclk;
+ else
+ return i2s->iis_pclk;
+}
+EXPORT_SYMBOL_GPL(s3c_i2sv2_get_clock);
+
/* default table of all avaialable root fs divisors */
static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
@@ -620,18 +637,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
}
EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate);
-int s3c_i2sv2_probe(struct platform_device *pdev,
- struct snd_soc_dai *dai,
+int s3c_i2sv2_probe(struct snd_soc_dai *dai,
struct s3c_i2sv2_info *i2s,
unsigned long base)
{
- struct device *dev = &pdev->dev;
+ struct device *dev = dai->dev;
unsigned int iismod;
i2s->dev = dev;
/* record our i2s structure for later use in the callbacks */
- dai->private_data = i2s;
+ snd_soc_dai_set_drvdata(dai, i2s);
i2s->regs = ioremap(base, 0x100);
if (i2s->regs == NULL) {
@@ -639,10 +655,14 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
return -ENXIO;
}
+ i2s->iis_pclk = clk_get(dev, "iis");
+ if (IS_ERR(i2s->iis_pclk)) {
+ dev_err(dev, "failed to get iis_clock\n");
+ iounmap(i2s->regs);
+ return -ENOENT;
+ }
-#if defined(CONFIG_PLAT_S5P)
- writel(((1<<0)|(1<<31)), i2s->regs + S3C2412_IISCON);
-#endif
+ clk_enable(i2s->iis_pclk);
/* Mark ourselves as in TXRX mode so we can run through our cleanup
* process without warnings. */
@@ -657,35 +677,29 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
#ifdef CONFIG_PM
-
-#include <mach/map.h>
-#define S3C_VA_AUDSS S3C_ADDR(0x01600000) /* Audio SubSystem */
-#include <mach/regs-audss.h>
static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
{
struct s3c_i2sv2_info *i2s = to_info(dai);
u32 iismod;
- i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
- i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
- i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
+ if (dai->active) {
+ i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
+ i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
+ i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
- /* Is this dai for I2Sv5? */
- if(dai->id == 0)
- i2s->suspend_audss_clksrc = readl(S5P_CLKSRC_AUDSS);
+ /* some basic suspend checks */
- /* some basic suspend checks */
+ iismod = readl(i2s->regs + S3C2412_IISMOD);
- iismod = readl(i2s->regs + S3C2412_IISMOD);
-
- if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
- pr_warning("%s: RXDMA active?\n", __func__);
+ if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
+ pr_warning("%s: RXDMA active?\n", __func__);
- if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
- pr_warning("%s: TXDMA active?\n", __func__);
+ if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
+ pr_warning("%s: TXDMA active?\n", __func__);
- if (iismod & S3C2412_IISCON_IIS_ACTIVE)
- pr_warning("%s: IIS active\n", __func__);
+ if (iismod & S3C2412_IISCON_IIS_ACTIVE)
+ pr_warning("%s: IIS active\n", __func__);
+ }
return 0;
}
@@ -697,19 +711,17 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
- writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
- writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
- writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
+ if (dai->active) {
+ writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
+ writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
+ writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
- /* Is this dai for I2Sv5? */
- if(dai->id == 0)
- writel(i2s->suspend_audss_clksrc, S5P_CLKSRC_AUDSS);
+ writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
+ i2s->regs + S3C2412_IISFIC);
- writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
- i2s->regs + S3C2412_IISFIC);
-
- ndelay(250);
- writel(0x0, i2s->regs + S3C2412_IISFIC);
+ ndelay(250);
+ writel(0x0, i2s->regs + S3C2412_IISFIC);
+ }
return 0;
}
@@ -718,19 +730,26 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
#define s3c2412_i2s_resume NULL
#endif
-int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
+int s3c_i2sv2_register_dai(struct device *dev, int id,
+ struct snd_soc_dai_driver *drv)
{
- struct snd_soc_dai_ops *ops = dai->ops;
+ struct snd_soc_dai_ops *ops = drv->ops;
ops->trigger = s3c2412_i2s_trigger;
- ops->hw_params = s3c2412_i2s_hw_params;
+ if (!ops->hw_params)
+ ops->hw_params = s3c_i2sv2_hw_params;
ops->set_fmt = s3c2412_i2s_set_fmt;
ops->set_clkdiv = s3c2412_i2s_set_clkdiv;
+ ops->set_sysclk = s3c_i2sv2_set_sysclk;
+
+ /* Allow overriding by (for example) IISv4 */
+ if (!ops->delay)
+ ops->delay = s3c2412_i2s_delay;
- dai->suspend = s3c2412_i2s_suspend;
- dai->resume = s3c2412_i2s_resume;
+ drv->suspend = s3c2412_i2s_suspend;
+ drv->resume = s3c2412_i2s_resume;
- return snd_soc_register_dai(dai);
+ return snd_soc_register_dai(dev, drv);
}
EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
diff --git a/sound/soc/samsung/s3c-i2s-v2.h b/sound/soc/samsung/s3c-i2s-v2.h
index f77e0ad..f8297d9 100644
--- a/sound/soc/samsung/s3c-i2s-v2.h
+++ b/sound/soc/samsung/s3c-i2s-v2.h
@@ -1,4 +1,4 @@
-/* sound/soc/s3c24xx/s3c-i2s-v2.h
+/* sound/soc/samsung/s3c-i2s-v2.h
*
* ALSA Soc Audio Layer - S3C_I2SV2 I2S driver
*
@@ -25,10 +25,20 @@
#define S3C_I2SV2_DIV_RCLK (2)
#define S3C_I2SV2_DIV_PRESCALER (3)
+#define S3C_I2SV2_CLKSRC_PCLK 0
+#define S3C_I2SV2_CLKSRC_AUDIOBUS 1
+#define S3C_I2SV2_CLKSRC_CDCLK 2
+
+/* Set this flag for I2S controllers that have the bit IISMOD[12]
+ * bridge/break RCLK signal and external Xi2sCDCLK pin.
+ */
+#define S3C_FEATURE_CDCLKCON (1 << 0)
+
/**
* struct s3c_i2sv2_info - S3C I2S-V2 information
* @dev: The parent device passed to use from the probe.
* @regs: The pointer to the device registe block.
+ * @feature: Set of bit-flags indicating features of the controller.
* @master: True if the I2S core is the I2S bit clock master.
* @dma_playback: DMA information for playback channel.
* @dma_capture: DMA information for capture channel.
@@ -43,12 +53,10 @@ struct s3c_i2sv2_info {
struct device *dev;
void __iomem *regs;
- struct clk *sclk_audio;
- struct clk *iis_ipclk;
+ u32 feature;
+
+ struct clk *iis_pclk;
struct clk *iis_cclk;
- struct clk *iis_clk;
- struct clk *iis_busclk;
- struct regulator *regulator;
unsigned char master;
@@ -58,12 +66,12 @@ struct s3c_i2sv2_info {
u32 suspend_iismod;
u32 suspend_iiscon;
u32 suspend_iispsr;
- u32 suspend_iisahb;
- u32 suspend_audss_clksrc;
- u32 suspend_audss_clkdiv;
- u32 suspend_audss_clkgate;
+
+ unsigned long base;
};
+extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai);
+
struct s3c_i2sv2_rate_calc {
unsigned int clk_div; /* for prescaler */
unsigned int fs_div; /* for root frame clock */
@@ -75,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
/**
* s3c_i2sv2_probe - probe for i2s device helper
- * @pdev: The platform device supplied to the original probe.
* @dai: The ASoC DAI structure supplied to the original probe.
* @i2s: Our local i2s structure to fill in.
* @base: The base address for the registers.
*/
-extern int s3c_i2sv2_probe(struct platform_device *pdev,
- struct snd_soc_dai *dai,
+extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
struct s3c_i2sv2_info *i2s,
unsigned long base);
/**
* s3c_i2sv2_register_dai - register dai with soc core
- * @dai: The snd_soc_dai structure to register
+ * @dev: DAI device
+ * @id: DAI ID
+ * @drv: The driver structure to register
*
* Fill in any missing fields and then register the given dai with the
* soc core.
*/
-extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
+extern int s3c_i2sv2_register_dai(struct device *dev, int id,
+ struct snd_soc_dai_driver *drv);
#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
diff --git a/sound/soc/samsung/s3c-idma.c b/sound/soc/samsung/s3c-idma.c
index 08fcc0d..c3b8c74 100644
--- a/sound/soc/samsung/s3c-idma.c
+++ b/sound/soc/samsung/s3c-idma.c
@@ -508,16 +508,15 @@ static int s3c_idma_pcm_new(struct snd_card *card,
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->playback.channels_min)
+ if (dai->driver->playback.channels_min)
ret = s3c_idma_preallocate_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
return ret;
}
-struct snd_soc_platform idma_soc_platform = {
- .name = "s5p-lp-audio",
- .pcm_ops = &s3c_idma_ops,
+struct snd_soc_platform_driver idma_soc_platform = {
+ .ops = &s3c_idma_ops,
.pcm_new = s3c_idma_pcm_new,
.pcm_free = s3c_idma_pcm_free,
};
diff --git a/sound/soc/samsung/s3c-idma.h b/sound/soc/samsung/s3c-idma.h
index 2c89230..351c3c3 100644
--- a/sound/soc/samsung/s3c-idma.h
+++ b/sound/soc/samsung/s3c-idma.h
@@ -29,7 +29,9 @@
#define LPAM_DMA_STOP 0
#define LPAM_DMA_START 1
-extern struct snd_soc_platform idma_soc_platform;
+extern struct snd_soc_platform_driver idma_soc_platform;
extern int i2s_trigger_stop;
extern bool audio_clk_gated ;
+void s5p_idma_init(void *regs);
+
#endif /* __S3C_IDMA_H_ */
diff --git a/sound/soc/samsung/s5p-i2s_sec.c b/sound/soc/samsung/s5p-i2s_sec.c
index 59e9115..747dd1c 100644
--- a/sound/soc/samsung/s5p-i2s_sec.c
+++ b/sound/soc/samsung/s5p-i2s_sec.c
@@ -25,6 +25,7 @@
#include <mach/regs-audss.h>
#include <mach/dma.h>
#include "s3c-dma.h"
+#include "s3c-idma.h"
#include "s3c-i2s-v2.h"
#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
@@ -49,7 +50,7 @@ static struct s3c_dma_params s5p_i2s_sec_pcm_out = {
static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
{
- return cpu_dai->private_data;
+ return snd_soc_dai_get_drvdata(cpu_dai);
}
static void s5p_snd_rxctrl(int on)
@@ -226,7 +227,7 @@ int s5p_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
- snd_soc_dai_set_dma_data(rtd->dai->cpu_dai,
+ snd_soc_dai_set_dma_data(rtd->cpu_dai,
substream, &s5p_i2s_sec_pcm_out);
iismod = readl(s5p_i2s0_regs + S3C2412_IISMOD);
diff --git a/sound/soc/samsung/s5pc1xx-i2s.c b/sound/soc/samsung/s5pc1xx-i2s.c
index ca738d9..674ccaa 100644
--- a/sound/soc/samsung/s5pc1xx-i2s.c
+++ b/sound/soc/samsung/s5pc1xx-i2s.c
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
+#include <sound/pcm_params.h>
#include <plat/regs-iis.h>
#include <plat/audio.h>
@@ -53,9 +54,9 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3];
static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3];
static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3];
-struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3];
+static struct snd_soc_dai_driver s3c64xx_i2s_dai_driver[MAX_I2SV3];
bool audio_clk_gated; /* At first, clock & i2s0_pd is enabled in probe() */
-EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
+//EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
/* For I2S Clock/Power Gating */
static int tx_clk_enabled ;
@@ -78,7 +79,7 @@ void dump_i2s(struct s3c_i2sv2_info *i2s)
static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
{
- return cpu_dai->private_data;
+ return snd_soc_dai_get_drvdata(cpu_dai);
}
struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
@@ -123,6 +124,77 @@ void s5p_i2s_set_clk_enabled(struct snd_soc_dai *dai, bool state)
}
}
+static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ u32 iismod;
+
+ pr_debug("Entered %s\n", __func__);
+
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dai_set_dma_data(dai, substream,
+ i2s->dma_playback);
+ else
+ snd_soc_dai_set_dma_data(dai, substream,
+ i2s->dma_capture);
+
+ /* Working copies of register */
+ iismod = readl(i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: r: IISMOD: %x\n", __func__, iismod);
+
+ switch (params_channels(params)) {
+ case 1:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ i2s->dma_playback->dma_size = 2;
+ else
+ i2s->dma_capture->dma_size = 2;
+ break;
+ case 2:
+ break;
+ default:
+ break;
+ }
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ iismod |= S3C2412_IISMOD_8BIT;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ iismod &= ~S3C2412_IISMOD_8BIT;
+ break;
+ }
+#endif
+
+#if defined(CONFIG_PLAT_S3C64XX) || defined(CONFIG_PLAT_S5P)
+ iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
+ /* Sample size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ /* 8 bit sample, 16fs BCLK */
+ iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /* 16 bit sample, 32fs BCLK */
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ /* 24 bit sample, 48fs BCLK */
+ iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
+ break;
+ }
+
+ /* Set the IISMOD[25:24](BLC_P) to same value */
+ iismod &= ~(S5P_IISMOD_BLCPMASK);
+ iismod |= ((iismod & S3C64XX_IISMOD_BLC_MASK) << 11);
+#endif
+
+ writel(iismod, i2s->regs + S3C2412_IISMOD);
+ pr_debug("%s: w: IISMOD: %x\n", __func__, iismod);
+ return 0;
+}
+
static int s5p_i2s_wr_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -138,6 +210,264 @@ static int s5p_i2s_wr_hw_params(struct snd_pcm_substream *substream,
#endif
return 0;
}
+
+#define S3C2412_I2S_DEBUG_CON 1
+
+#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
+
+#if S3C2412_I2S_DEBUG_CON
+static void dbg_showcon(const char *fn, u32 con)
+{
+ printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d,\
+ RXFFULL=%d\n", fn,
+ bit_set(con, S3C2412_IISCON_LRINDEX),
+ bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
+ bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
+ bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
+ bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
+
+ printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
+ fn,
+ bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
+ bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
+ bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
+ bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
+ printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
+ bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
+ bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
+ bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
+}
+#else
+static inline void dbg_showcon(const char *fn, u32 con)
+{
+}
+#endif
+
+/* Turn on or off the transmission path. */
+static void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
+{
+ void __iomem *regs = i2s->regs;
+ u32 fic, con, mod;
+
+ pr_debug("%s(%d)\n", __func__, on);
+
+ fic = readl(regs + S3C2412_IISFIC);
+ con = readl(regs + S3C2412_IISCON);
+ mod = readl(regs + S3C2412_IISMOD);
+
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+
+ if (on) {
+ con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+ con &= ~S3C2412_IISCON_TXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_TXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXONLY:
+ case S3C2412_IISMOD_MODE_TXRX:
+ /* do nothing, we are in the right mode */
+ break;
+
+ case S3C2412_IISMOD_MODE_RXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXRX;
+ break;
+
+ default:
+ dev_err(i2s->dev, "TXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ break;
+ }
+
+ writel(con, regs + S3C2412_IISCON);
+ writel(mod, regs + S3C2412_IISMOD);
+ } else {
+ /* Note, we do not have any indication that the FIFO problems
+ * tha the S3C2410/2440 had apply here, so we should be able
+ * to disable the DMA and TX without resetting the FIFOS.
+ */
+
+ con |= S3C2412_IISCON_TXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
+ if (con & S5P_IISCON_TXSDMACTIVE) { /* If sec is active */
+ writel(con, regs + S3C2412_IISCON);
+ return;
+ }
+ con |= S3C2412_IISCON_TXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXRX:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_RXONLY;
+ break;
+
+ case S3C2412_IISMOD_MODE_TXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ con &= ~S3C2412_IISCON_IIS_ACTIVE;
+ break;
+
+ default:
+ dev_err(i2s->dev, "TXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ break;
+ }
+
+ writel(mod, regs + S3C2412_IISMOD);
+ writel(con, regs + S3C2412_IISCON);
+ }
+
+ fic = readl(regs + S3C2412_IISFIC);
+ dbg_showcon(__func__, con);
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
+{
+ void __iomem *regs = i2s->regs;
+ u32 fic, con, mod;
+
+ pr_debug("%s(%d)\n", __func__, on);
+
+ fic = readl(regs + S3C2412_IISFIC);
+ con = readl(regs + S3C2412_IISCON);
+ mod = readl(regs + S3C2412_IISMOD);
+
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+
+ if (on) {
+ con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
+ con &= ~S3C2412_IISCON_RXDMA_PAUSE;
+ con &= ~S3C2412_IISCON_RXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_TXRX:
+ case S3C2412_IISMOD_MODE_RXONLY:
+ /* do nothing, we are in the right mode */
+ break;
+
+ case S3C2412_IISMOD_MODE_TXONLY:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXRX;
+ break;
+
+ default:
+ dev_err(i2s->dev, "RXEN: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ }
+
+ writel(mod, regs + S3C2412_IISMOD);
+ writel(con, regs + S3C2412_IISCON);
+ } else {
+ /* See txctrl notes on FIFOs. */
+
+ con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
+ con |= S3C2412_IISCON_RXDMA_PAUSE;
+ con |= S3C2412_IISCON_RXCH_PAUSE;
+
+ switch (mod & S3C2412_IISMOD_MODE_MASK) {
+ case S3C2412_IISMOD_MODE_RXONLY:
+ con &= ~S3C2412_IISCON_IIS_ACTIVE;
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ break;
+
+ case S3C2412_IISMOD_MODE_TXRX:
+ mod &= ~S3C2412_IISMOD_MODE_MASK;
+ mod |= S3C2412_IISMOD_MODE_TXONLY;
+ break;
+
+ default:
+ dev_err(i2s->dev, "RXDIS: Invalid MODE %x in IISMOD\n",
+ mod & S3C2412_IISMOD_MODE_MASK);
+ }
+
+ writel(con, regs + S3C2412_IISCON);
+ writel(mod, regs + S3C2412_IISMOD);
+ }
+
+ fic = readl(regs + S3C2412_IISFIC);
+ pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
+}
+
+/*
+ * Wait for the LR signal to allow synchronisation to the L/R clock
+ * from the codec. May only be needed for slave mode.
+ */
+static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
+{
+ u32 iiscon;
+ unsigned long loops = msecs_to_loops(5);
+
+ pr_debug("Entered %s\n", __func__);
+
+ while (--loops) {
+ iiscon = readl(i2s->regs + S3C2412_IISCON);
+ if (iiscon & S3C2412_IISCON_LRINDEX)
+ break;
+
+ cpu_relax();
+ }
+
+ if (!loops) {
+ printk(KERN_ERR "%s: timeout\n", __func__);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct s3c_i2sv2_info *i2s = to_info(dai);
+ int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
+ unsigned long irqs;
+ int ret = 0;
+
+ pr_debug("Entered %s\n", __func__);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!i2s->master) {
+ ret = s3c2412_snd_lrsync(i2s);
+ if (ret)
+ goto exit_err;
+ }
+
+ local_irq_save(irqs);
+
+ if (capture)
+ s3c2412_snd_rxctrl(i2s, 1);
+ else
+ s3c2412_snd_txctrl(i2s, 1);
+
+ local_irq_restore(irqs);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ local_irq_save(irqs);
+
+ if (capture)
+ s3c2412_snd_rxctrl(i2s, 0);
+ else
+ s3c2412_snd_txctrl(i2s, 0);
+
+ local_irq_restore(irqs);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+exit_err:
+ return ret;
+}
+
static int s5p_i2s_wr_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
@@ -510,7 +840,7 @@ static void s5p_i2s_wr_shutdown(struct snd_pcm_substream *substream,
(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static void s3c64xx_iis_dai_init(struct snd_soc_dai *dai)
+static void s3c64xx_iis_dai_init(struct snd_soc_dai_driver *dai)
{
dai->name = "s5pc1xx-i2s";
dai->playback.channels_min = 2;
@@ -581,7 +911,7 @@ static int s5p_i2s_resume(struct snd_soc_dai *dai)
#define s3c2412_i2s_resume NULL
#endif /* CONFIG_PM */
-int s5p_i2sv5_register_dai(struct snd_soc_dai *dai)
+int s5p_i2sv5_register_dai(struct device *dev, struct snd_soc_dai_driver *dai)
{
struct snd_soc_dai_ops *ops = dai->ops;
@@ -595,14 +925,14 @@ int s5p_i2sv5_register_dai(struct snd_soc_dai *dai)
/* suspend/resume are not necessary due to Clock/Pwer gating scheme */
dai->suspend = s5p_i2s_suspend;
dai->resume = s5p_i2s_resume;
- return snd_soc_register_dai(dai);
+ return snd_soc_register_dai(dev, dai);
}
static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
{
struct s3c_audio_pdata *i2s_pdata;
struct s3c_i2sv2_info *i2s;
- struct snd_soc_dai *dai;
+ struct snd_soc_dai_driver *dai;
struct resource *res;
struct clk *fout_epll, *mout_epll;
struct clk *mout_audss = NULL;
@@ -616,8 +946,8 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
i2s = &s3c64xx_i2s[pdev->id];
i2s->dev = &pdev->dev;
- dai = &s3c64xx_i2s_dai[pdev->id];
- dai->dev = &pdev->dev;
+ dai = &s3c64xx_i2s_dai_driver[pdev->id];
+ //dai->dev = &pdev->dev;
dai->id = pdev->id;
s3c64xx_iis_dai_init(dai);
@@ -660,7 +990,8 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
i2s_pdata = pdev->dev.platform_data;
- dai->private_data = i2s;
+ //dai->private_data = i2s;
+ dev_set_drvdata(&pdev->dev, i2s);
base = i2s->dma_playback->dma_addr - S3C2412_IISTXD;
i2s->regs = ioremap(base, 0x100);
@@ -760,7 +1091,7 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
s5p_i2s_sec_init(i2s->regs, base);
#endif
- ret = s5p_i2sv5_register_dai(dai);
+ ret = s5p_i2sv5_register_dai(&pdev->dev, dai);
if (ret != 0)
goto err_i2sv5;
@@ -798,7 +1129,7 @@ static struct platform_driver s3c64xx_iis_driver = {
.probe = s3c64xx_iis_dev_probe,
.remove = s3c64xx_iis_dev_remove,
.driver = {
- .name = "s5pc1xx-iis",
+ .name = "samsung-i2s",
.owner = THIS_MODULE,
},
};
diff --git a/sound/soc/samsung/s5pc1xx-i2s.h b/sound/soc/samsung/s5pc1xx-i2s.h
index 8d36fb3..b754cd5 100644
--- a/sound/soc/samsung/s5pc1xx-i2s.h
+++ b/sound/soc/samsung/s5pc1xx-i2s.h
@@ -17,7 +17,84 @@
struct clk;
-#include "s3c-i2s-v2.h"
+//#include "s3c-i2s-v2.h"
+//==
+
+#define S3C_I2SV2_DIV_BCLK (1)
+#define S3C_I2SV2_DIV_RCLK (2)
+#define S3C_I2SV2_DIV_PRESCALER (3)
+
+/**
+ * struct s3c_i2sv2_info - S3C I2S-V2 information
+ * @dev: The parent device passed to use from the probe.
+ * @regs: The pointer to the device registe block.
+ * @master: True if the I2S core is the I2S bit clock master.
+ * @dma_playback: DMA information for playback channel.
+ * @dma_capture: DMA information for capture channel.
+ * @suspend_iismod: PM save for the IISMOD register.
+ * @suspend_iiscon: PM save for the IISCON register.
+ * @suspend_iispsr: PM save for the IISPSR register.
+ *
+ * This is the private codec state for the hardware associated with an
+ * I2S channel such as the register mappings and clock sources.
+ */
+struct s3c_i2sv2_info {
+ struct device *dev;
+ void __iomem *regs;
+
+ struct clk *sclk_audio;
+ struct clk *iis_ipclk;
+ struct clk *iis_cclk;
+ struct clk *iis_clk;
+ struct clk *iis_busclk;
+ struct regulator *regulator;
+
+ unsigned char master;
+
+ struct s3c_dma_params *dma_playback;
+ struct s3c_dma_params *dma_capture;
+
+ u32 suspend_iismod;
+ u32 suspend_iiscon;
+ u32 suspend_iispsr;
+ u32 suspend_iisahb;
+ u32 suspend_audss_clksrc;
+ u32 suspend_audss_clkdiv;
+ u32 suspend_audss_clkgate;
+};
+
+struct s3c_i2sv2_rate_calc {
+ unsigned int clk_div; /* for prescaler */
+ unsigned int fs_div; /* for root frame clock */
+};
+
+extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
+ unsigned int *fstab,
+ unsigned int rate, struct clk *clk);
+
+/**
+ * s3c_i2sv2_probe - probe for i2s device helper
+ * @pdev: The platform device supplied to the original probe.
+ * @dai: The ASoC DAI structure supplied to the original probe.
+ * @i2s: Our local i2s structure to fill in.
+ * @base: The base address for the registers.
+ */
+extern int s3c_i2sv2_probe(struct platform_device *pdev,
+ struct snd_soc_dai *dai,
+ struct s3c_i2sv2_info *i2s,
+ unsigned long base);
+
+/**
+ * s3c_i2sv2_register_dai - register dai with soc core
+ * @dai: The snd_soc_dai structure to register
+ *
+ * Fill in any missing fields and then register the given dai with the
+ * soc core.
+ */
+extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
+extern void s5p_idma_init(void *);
+
+//==
#define USE_CLKAUDIO 1
@@ -42,12 +119,6 @@ extern int s5p_i2s_hw_params(struct snd_pcm_substream *substream,
extern int s5p_i2s_startup(struct snd_soc_dai *dai);
extern int s5p_i2s_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai);
-extern int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai);
-extern int s3c2412_i2s_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai);
-
extern void s5p_i2s_sec_init(void *, dma_addr_t);
#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */