#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/gpio.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/wm8994/pdata.h>
+
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/i2c-gpio.h>
};
#endif
+
+/*****************************************************************************************
+ * wm8994 codec
+ * author: qjb@rock-chips.com
+ *****************************************************************************************/
+#if defined(CONFIG_MFD_WM8994)
+static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
+ REGULATOR_SUPPLY("DBVDD", "5-001a"),
+ REGULATOR_SUPPLY("AVDD2", "5-001a"),
+ REGULATOR_SUPPLY("CPVDD", "5-001a"),
+};
+
+static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
+ REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
+ REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
+};
+
+static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage0_supplies),
+ .consumer_supplies = wm8994_fixed_voltage0_supplies,
+};
+
+static struct regulator_init_data wm8994_fixed_voltage1_init_data = {
+ .constraints = {
+ .always_on = 1,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(wm8994_fixed_voltage1_supplies),
+ .consumer_supplies = wm8994_fixed_voltage1_supplies,
+};
+
+static struct fixed_voltage_config wm8994_fixed_voltage0_config = {
+ .supply_name = "VCC_1.8V_PDA",
+ .microvolts = 1800000,
+ .gpio = -EINVAL,
+ .init_data = &wm8994_fixed_voltage0_init_data,
+};
+
+static struct fixed_voltage_config wm8994_fixed_voltage1_config = {
+ .supply_name = "V_BAT",
+ .microvolts = 3700000,
+ .gpio = -EINVAL,
+ .init_data = &wm8994_fixed_voltage1_init_data,
+};
+
+static struct platform_device wm8994_fixed_voltage0 = {
+ .name = "reg-fixed-voltage",
+ .id = 0,
+ .dev = {
+ .platform_data = &wm8994_fixed_voltage0_config,
+ },
+};
+
+static struct platform_device wm8994_fixed_voltage1 = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &wm8994_fixed_voltage1_config,
+ },
+};
+
+static struct regulator_consumer_supply wm8994_avdd1_supply =
+ REGULATOR_SUPPLY("AVDD1", "5-001a");
+
+static struct regulator_consumer_supply wm8994_dcvdd_supply =
+ REGULATOR_SUPPLY("DCVDD", "5-001a");
+
+
+
+static struct regulator_init_data wm8994_ldo1_data = {
+ .constraints = {
+ .name = "AVDD1_3.0V",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &wm8994_avdd1_supply,
+};
+
+static struct regulator_init_data wm8994_ldo2_data = {
+ .constraints = {
+ .name = "DCVDD_1.0V",
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &wm8994_dcvdd_supply,
+};
+
+static struct wm8994_pdata wm8994_platform_data = {
+#if defined (CONFIG_GPIO_WM8994)
+ .gpio_base = WM8994_GPIO_EXPANDER_BASE,
+ //Fill value to initialize the GPIO
+ .gpio_defaults ={},
+#endif
+ /* configure gpio1 function: 0x0001(Logic level input/output) */
+// .gpio_defaults[0] = 0x0001,
+ /* configure gpio3/4/5/7 function for AIF2 voice */
+// .gpio_defaults[2] = 0x8100,
+// .gpio_defaults[3] = 0x8100,
+// .gpio_defaults[4] = 0x8100,
+// .gpio_defaults[6] = 0x0100,
+ /* configure gpio8/9/10/11 function for AIF3 BT */
+// .gpio_defaults[7] = 0x8100,
+// .gpio_defaults[8] = 0x0100,
+// .gpio_defaults[9] = 0x0100,
+// .gpio_defaults[10] = 0x0100,
+ .ldo[0] = { RK29_PIN5_PA1, NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
+ .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+
+ .micdet_irq = 0,
+ .irq_base = 0,
+};
+#endif
+
#ifdef CONFIG_RK_HEADSET_DET
#define HEADSET_GPIO RK29_PIN4_PD2
struct rk_headset_pdata rk_headset_info = {
.Headset_gpio = RK29_PIN4_PD2,
.headset_in_type= HEADSET_IN_HIGH,
- .Hook_gpio = RK29_PIN4_PD1,//Detection Headset--Must be set
+// .Hook_gpio = RK29_PIN4_PD1,//Detection Headset--Must be set
.hook_key_code = KEY_MEDIA,
};
.type = "wm8994",
.addr = 0x1a,
.flags = 0,
+ #if defined(CONFIG_MFD_WM8994)
+ .platform_data = &wm8994_platform_data,
+ #endif
},
#endif
#if defined (CONFIG_BATTERY_STC3100)
&rk29_device_i2c3,
#endif
+#ifdef CONFIG_MFD_WM8994
+ &wm8994_fixed_voltage0,
+ &wm8994_fixed_voltage1,
+#endif
+
#ifdef CONFIG_SND_RK29_SOC_I2S_2CH
&rk29_device_iis_2ch,
#endif
gpio_request(POWER_ON_PIN,"poweronpin");
gpio_set_value(POWER_ON_PIN, GPIO_HIGH);
- gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
+ gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
+
pm_power_off = rk29_pm_power_off;
//arm_pm_restart = rk29_pm_power_restart;
// enable_irq(headset_info->irq[HOOK]);
headset_info->cur_headset_status = BIT_HEADSET;
headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);//
- if (pdata->Headset_gpio != NULL) {
+ if (pdata->Hook_gpio != NULL) {
del_timer(&headset_info->headset_timer);//Start the timer, wait for switch to the headphone channel
headset_info->headset_timer.expires = jiffies + 500;
add_timer(&headset_info->headset_timer);
// DBG("---HEADSET_IN_LOW headset in LOW ---\n");
headset_info->cur_headset_status = BIT_HEADSET;
headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);//
- if (pdata->Headset_gpio != NULL) {
+ if (pdata->Hook_gpio != NULL) {
del_timer(&headset_info->headset_timer);//Start the timer, wait for switch to the headphone channel
headset_info->headset_timer.expires = jiffies + 500;
add_timer(&headset_info->headset_timer);
- }
+ }
}
else if(level > 0)
{//out--High level
#include <linux/mfd/wm8994/core.h>
#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/wm8994/registers.h>
-#include <mach/gpio.h>
-
-#define WM_PW_EN RK29_PIN5_PA1
+#if 0
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...) do { } while (0)
+#endif
static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
int bytes, void *dest)
{
dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
be16_to_cpu(buf[i]), reg + i, reg + i);
}
+
return 0;
}
ret = wm8994_read(wm8994, reg, 2, &val);
mutex_unlock(&wm8994->io_lock);
-
+ DBG("%s:0x%04x = 0x%04x\n",__FUNCTION__,reg,be16_to_cpu(val));
if (ret < 0)
return ret;
else
dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
be16_to_cpu(buf[i]), reg + i, reg + i);
}
+
return wm8994->write_dev(wm8994, reg, bytes, src);
}
int ret;
val = cpu_to_be16(val);
-
+ DBG("%s:0x%04x = 0x%04x\n",__FUNCTION__,reg,val);
mutex_lock(&wm8994->io_lock);
ret = wm8994_write(wm8994, reg, 2, &val);
* management.
*/
static const char *wm8994_main_supplies[] = {
- "DBVDD",
- "DCVDD",
- "AVDD1",
- "AVDD2",
- "CPVDD",
- "SPKVDD1",
- "SPKVDD2",
+// "DBVDD",
+// "DCVDD",
+// "AVDD1",
+// "AVDD2",
+// "CPVDD",
+// "SPKVDD1",
+// "SPKVDD2",
};
static const char *wm8958_main_supplies[] = {
};
#ifdef CONFIG_PM
-int wm8994_suspend(struct wm8994 *wm8994)
+static int wm8994_suspend(struct device *dev)
{
+ struct wm8994 *wm8994 = dev_get_drvdata(dev);
int ret;
/* Don't actually go through with the suspend if the CODEC is
* still active (eg, for audio passthrough from CP. */
ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_1);
if (ret < 0) {
- dev_err(wm8994->dev, "Failed to read power status: %d\n", ret);
+ dev_err(dev, "Failed to read power status: %d\n", ret);
} else if (ret & WM8994_VMID_SEL_MASK) {
- dev_dbg(wm8994->dev, "CODEC still active, ignoring suspend\n");
+ dev_dbg(dev, "CODEC still active, ignoring suspend\n");
return 0;
}
ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
&wm8994->gpio_regs);
if (ret < 0)
- dev_err(wm8994->dev, "Failed to save GPIO registers: %d\n", ret);
+ dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
/* For similar reasons we also stash the regulator states */
ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
&wm8994->ldo_regs);
if (ret < 0)
- dev_err(wm8994->dev, "Failed to save LDO registers: %d\n", ret);
+ dev_err(dev, "Failed to save LDO registers: %d\n", ret);
/* Explicitly put the device into reset in case regulators
* don't get disabled in order to ensure consistent restart.
wm8994->suspended = true;
-/* ret = regulator_bulk_disable(wm8994->num_supplies,
+ ret = regulator_bulk_disable(wm8994->num_supplies,
wm8994->supplies);
if (ret != 0) {
dev_err(dev, "Failed to disable supplies: %d\n", ret);
return ret;
}
-*/
-
- gpio_set_value(WM_PW_EN, GPIO_LOW);
return 0;
}
-int wm8994_resume(struct wm8994 *wm8994)
+static int wm8994_resume(struct device *dev)
{
+ struct wm8994 *wm8994 = dev_get_drvdata(dev);
int ret;
/* We may have lied to the PM core about suspending */
if (!wm8994->suspended)
return 0;
- gpio_set_value(WM_PW_EN, GPIO_HIGH);
- msleep(50);
-
-/* ret = regulator_bulk_enable(wm8994->num_supplies,
+ ret = regulator_bulk_enable(wm8994->num_supplies,
wm8994->supplies);
if (ret != 0) {
dev_err(dev, "Failed to enable supplies: %d\n", ret);
return ret;
}
-*/
+
ret = wm8994_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK,
WM8994_NUM_IRQ_REGS * 2, &wm8994->irq_masks_cur);
if (ret < 0)
- dev_err(wm8994->dev, "Failed to restore interrupt masks: %d\n", ret);
+ dev_err(dev, "Failed to restore interrupt masks: %d\n", ret);
ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
&wm8994->ldo_regs);
if (ret < 0)
- dev_err(wm8994->dev, "Failed to restore LDO registers: %d\n", ret);
+ dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
&wm8994->gpio_regs);
if (ret < 0)
- dev_err(wm8994->dev, "Failed to restore GPIO registers: %d\n", ret);
+ dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
wm8994->suspended = false;
goto err;
}
-/* switch (wm8994->type) {
+ switch (wm8994->type) {
case WM8994:
wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies);
break;
dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
goto err_get;
}
-*/
+
ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);
if (ret < 0) {
dev_err(wm8994->dev, "Failed to read ID register\n");
err_irq:
wm8994_irq_exit(wm8994);
err_enable:
-// regulator_bulk_disable(wm8994->num_supplies,
-// wm8994->supplies);
+ regulator_bulk_disable(wm8994->num_supplies,
+ wm8994->supplies);
err_get:
-// regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
+ regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
err_supplies:
-// kfree(wm8994->supplies);
+ kfree(wm8994->supplies);
err:
mfd_remove_devices(wm8994->dev);
kfree(wm8994);
pm_runtime_disable(wm8994->dev);
mfd_remove_devices(wm8994->dev);
wm8994_irq_exit(wm8994);
-// regulator_bulk_disable(wm8994->num_supplies,
-// wm8994->supplies);
-// regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
-// kfree(wm8994->supplies);
+ regulator_bulk_disable(wm8994->num_supplies,
+ wm8994->supplies);
+ regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
+ kfree(wm8994->supplies);
kfree(wm8994);
}
static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
int bytes, const void *src)
{
+
struct i2c_client *i2c = wm8994->control_data;
- struct i2c_msg xfer[2];
+ struct i2c_msg xfer;
+ unsigned char msg[bytes + 2];
int ret;
reg = cpu_to_be16(reg);
-
- xfer[0].addr = i2c->addr;
- xfer[0].flags = 0;
- xfer[0].len = 2;
- xfer[0].buf = (char *)®
- xfer[0].scl_rate = 100 * 1000;
-
- xfer[1].addr = i2c->addr;
- xfer[1].flags = I2C_M_NOSTART;
- xfer[1].len = bytes;
- xfer[1].buf = (char *)src;
- xfer[1].scl_rate = 100 * 1000;
-
- ret = i2c_transfer(i2c->adapter, xfer, 2);
+ memcpy(&msg[0], ®, 2);
+ memcpy(&msg[2], src, bytes);
+
+ xfer.addr = i2c->addr;
+ xfer.flags = i2c->flags;
+ xfer.len = bytes + 2;
+ xfer.buf = (char *)msg;
+ xfer.scl_rate = 100 * 1000;
+ xfer.udelay = i2c->udelay;
+ xfer.read_type = 0;
+
+ ret = i2c_transfer(i2c->adapter, &xfer, 1);
if (ret < 0)
return ret;
- if (ret != 2)
+ if (ret != 1)
return -EIO;
return 0;
}
-int wm8994_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int wm8994_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
{
struct wm8994 *wm8994;
-
- gpio_request(WM_PW_EN, NULL);
- gpio_direction_output(WM_PW_EN, GPIO_HIGH);
-
- msleep(50);
-
+
wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
if (wm8994 == NULL)
return -ENOMEM;
return wm8994_device_init(wm8994, i2c->irq);
}
-int wm8994_remove(struct i2c_client *i2c)
+static int wm8994_i2c_remove(struct i2c_client *i2c)
{
struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
return 0;
}
+
+static const struct i2c_device_id wm8994_i2c_id[] = {
+ { "wm8994", WM8994 },
+ { "wm8958", WM8958 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
+
+static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume,
+ NULL);
+
+static struct i2c_driver wm8994_i2c_driver = {
+ .driver = {
+ .name = "wm8994",
+ .owner = THIS_MODULE,
+ .pm = &wm8994_pm_ops,
+ },
+ .probe = wm8994_i2c_probe,
+ .remove = wm8994_i2c_remove,
+ .id_table = wm8994_i2c_id,
+};
+
+static int __init wm8994_i2c_init(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&wm8994_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register wm8994 I2C driver: %d\n", ret);
+
+ return ret;
+}
+module_init(wm8994_i2c_init);
+
+static void __exit wm8994_i2c_exit(void)
+{
+ i2c_del_driver(&wm8994_i2c_driver);
+}
+module_exit(wm8994_i2c_exit);
+
MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
.enable = wm8994_ldo_enable,
.disable = wm8994_ldo_disable,
.is_enabled = wm8994_ldo_is_enabled,
-// .enable_time = wm8994_ldo_enable_time,
+ .enable_time = wm8994_ldo_enable_time,
.list_voltage = wm8994_ldo1_list_voltage,
.get_voltage_sel = wm8994_ldo1_get_voltage_sel,
.enable = wm8994_ldo_enable,
.disable = wm8994_ldo_disable,
.is_enabled = wm8994_ldo_is_enabled,
-// .enable_time = wm8994_ldo_enable_time,
+ .enable_time = wm8994_ldo_enable_time,
.list_voltage = wm8994_ldo2_list_voltage,
.get_voltage_sel = wm8994_ldo2_get_voltage_sel,
if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
ldo->enable = pdata->ldo[id].enable;
+ ldo->is_enabled = true;
ret = gpio_request(ldo->enable, "WM8994 LDO enable");
if (ret < 0) {
#define __MFD_WM8994_CORE_H__
#include <linux/interrupt.h>
-#include <linux/i2c.h>
enum wm8994_type {
WM8994 = 0,
int wm8994_irq_init(struct wm8994 *wm8994);
void wm8994_irq_exit(struct wm8994 *wm8994);
-int wm8994_suspend(struct wm8994 *wm8994);
-int wm8994_resume(struct wm8994 *wm8994);
-
-int wm8994_probe(struct i2c_client *i2c, const struct i2c_device_id *id);
-int wm8994_remove(struct i2c_client *i2c);
-
#endif
#define WM8994_GP_FN_WSEQ_STATUS 16
#define WM8994_GP_FN_FIFO_ERROR 17
#define WM8994_GP_FN_OPCLK 18
+#define WM8994_GP_FN_THW 19
+#define WM8994_GP_FN_DCS_DONE 20
+#define WM8994_GP_FN_FLL1_OUT 21
+#define WM8994_GP_FN_FLL2_OUT 22
#define WM8994_GPN_DIR 0x8000 /* GPN_DIR */
#define WM8994_GPN_DIR_MASK 0x8000 /* GPN_DIR */
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
-#define DEBUG
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <trace/events/asoc.h>
+#include <mach/gpio.h>
#include <linux/mfd/wm8994/core.h>
#include <linux/mfd/wm8994/registers.h>
#include "wm8994.h"
#include "wm_hubs.h"
+#define WM8994_PROC
+#ifdef WM8994_PROC
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+char debug_write_read = 0;
+#endif
+
+#if 1
+#define DBG(x...) printk(KERN_INFO x)
+#else
+#define DBG(x...) do { } while (0)
+#endif
+
#define WM8994_NUM_DRC 3
#define WM8994_NUM_EQ 3
-struct wm8994 *wm8994_control;
+static struct snd_soc_codec *wm8994_codec;
static int wm8994_drc_base[] = {
WM8994_AIF1_DRC1_1,
int ret;
BUG_ON(reg > WM8994_MAX_REGISTER);
-
+#ifdef WM8994_PROC
+ if(debug_write_read != 0)
+ printk("%s:0x%04x = 0x%04x\n",__FUNCTION__,reg,value);
+#endif
if (!wm8994_volatile(codec, reg)) {
ret = snd_soc_cache_write(codec, reg, value);
if (ret != 0)
dev_err(codec->dev, "Cache write to %x failed: %d\n",
reg, ret);
+ // else
+ // DBG("snd_soc_cache_write:0x%04x = 0x%04x\n",reg,value);
}
return wm8994_reg_write(codec->control_data, reg, value);
int ret;
BUG_ON(reg > WM8994_MAX_REGISTER);
-
+
if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) &&
reg < codec->driver->reg_cache_size) {
ret = snd_soc_cache_read(codec, reg, &val);
if (ret >= 0)
+ {
+ // DBG("snd_soc_cache_read:0x%04x = 0x%04x\n",reg,val);
return val;
+ }
else
dev_err(codec->dev, "Cache read from %x failed: %d\n",
reg, ret);
}
-
- return wm8994_reg_read(codec->control_data, reg);
+ val = wm8994_reg_read(codec->control_data, reg);
+#ifdef WM8994_PROC
+ if(debug_write_read != 0)
+ printk("%s:0x%04x = 0x%04x",__FUNCTION__,reg,val);
+#endif
+ return val;
}
static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
return snd_soc_update_bits(codec, reg, mask, val);
}
-struct snd_soc_codec *wm8994_regshow_codec;
-
-static ssize_t wm8994_index_reg_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- #define IDX_REG_FMT "reg 0x%04x value 0x%04x\n"
- unsigned int val;
- int cnt = 0, i;
-
- cnt += sprintf(buf, "WM8994 index register\n");
- for (i = 0; i < WM8994_CACHE_SIZE; i++) {
- if (!wm8994_readable(wm8994_regshow_codec, i) || wm8994_volatile(wm8994_regshow_codec, i))
- continue;
- val = wm8994_reg_read(wm8994_control, i);
- if (!val)
- continue;
- cnt += sprintf(buf + cnt, IDX_REG_FMT, i, val);
- }
-
- if (cnt >= PAGE_SIZE)
- cnt = PAGE_SIZE - 1;
-
- return cnt;
-}
-static DEVICE_ATTR(index_reg, 0444, wm8994_index_reg_show, NULL);
-
#define WM8994_RATES SNDRV_PCM_RATE_8000_96000
#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
};
#ifdef CONFIG_PM
-static int wm8994_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = codec->control_data;
wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
- wm8994_suspend(control);
-
return 0;
}
-static int wm8994_codec_resume(struct snd_soc_codec *codec)
+static int wm8994_resume(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994 *control = codec->control_data;
int i, ret;
unsigned int val, mask;
- wm8994_resume(control);
-
if (wm8994->revision < 4) {
/* force a HW read */
val = wm8994_reg_read(codec->control_data,
return IRQ_HANDLED;
}
+#ifdef WM8994_PROC
+static int wm8994_proc_init(void);
+#endif
+
static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
struct wm8994 *control;
struct wm8994_priv *wm8994;
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret, i;
+
+#ifdef WM8994_PROC
+ wm8994_proc_init();
+#endif
- if (wm8994_control == NULL) {
- pr_err("wm8994_codec_probe:wm8994_control is NULL!");
- return -EIO;
- }
-
- codec->control_data = wm8994_control;//dev_get_drvdata(codec->dev->parent);
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
control = codec->control_data;
- wm8994_regshow_codec = codec;
-
wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
if (wm8994 == NULL)
return -ENOMEM;
snd_soc_codec_set_drvdata(codec, wm8994);
- wm8994->pdata = wm8994_control->dev->platform_data;//dev_get_platdata(codec->dev->parent);
+ wm8994->pdata = dev_get_platdata(codec->dev->parent);
wm8994->codec = codec;
-
+ wm8994_codec = codec;
+
if (wm8994->pdata && wm8994->pdata->micdet_irq)
wm8994->micdet_irq = wm8994->pdata->micdet_irq;
else if (wm8994->pdata && wm8994->pdata->irq_base)
}
- wm_hubs_add_analogue_routes(codec, 0, 0);
+ wm_hubs_add_analogue_routes(codec, 1, 0);
snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
switch (control->type) {
break;
}
- ret = device_create_file(codec->dev, &dev_attr_index_reg);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to create index_reg sysfs files: %d\n", ret);
- return ret;
- }
-
return 0;
err_irq:
static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.probe = wm8994_codec_probe,
.remove = wm8994_codec_remove,
- .suspend = wm8994_codec_suspend,
- .resume = wm8994_codec_resume,
+ .suspend = wm8994_suspend,
+ .resume = wm8994_resume,
.read = wm8994_read,
.write = wm8994_write,
.readable_register = wm8994_readable,
.compress_type = SND_SOC_RBTREE_COMPRESSION,
};
-static int wm8994_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static int __devinit wm8994_probe(struct platform_device *pdev)
{
- int ret;
-
- ret = wm8994_probe(i2c, id);
- if (ret < 0) {
- pr_err("wm8994_i2c_probe error!");
- return ret;
- }
-
- wm8994_control = i2c_get_clientdata(i2c);
-
- return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8994,
- wm8994_dai, ARRAY_SIZE(wm8994_dai));
+ return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
+ wm8994_dai, ARRAY_SIZE(wm8994_dai));
}
-static int wm8994_i2c_remove(struct i2c_client *i2c)
+static int __devexit wm8994_remove(struct platform_device *pdev)
{
- wm8994_remove(i2c);
- snd_soc_unregister_codec(&i2c->dev);
-
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
-static const struct i2c_device_id wm8994_i2c_id[] = {
- { "wm8994", WM8994 },
-// { "wm8958", WM8958 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
-
-//static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume,
-// NULL);
-
-static struct i2c_driver wm8994_i2c_driver = {
+static struct platform_driver wm8994_codec_driver = {
.driver = {
- .name = "WM8994",
- .owner = THIS_MODULE,
- //.pm = &wm8994_pm_ops,
- },
- .probe = wm8994_i2c_probe,
- .remove = wm8994_i2c_remove,
- .id_table = wm8994_i2c_id,
+ .name = "wm8994-codec",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8994_probe,
+ .remove = __devexit_p(wm8994_remove),
};
-static int __init wm8994_i2c_init(void)
+static __init int wm8994_init(void)
{
- int ret;
-
- ret = i2c_add_driver(&wm8994_i2c_driver);
- if (ret != 0)
- pr_err("Failed to register wm8994 I2C driver: %d\n", ret);
-
- return ret;
+ return platform_driver_register(&wm8994_codec_driver);
}
-module_init(wm8994_i2c_init);
+module_init(wm8994_init);
-static void __exit wm8994_i2c_exit(void)
+static __exit void wm8994_exit(void)
{
- i2c_del_driver(&wm8994_i2c_driver);
+ platform_driver_unregister(&wm8994_codec_driver);
}
-module_exit(wm8994_i2c_exit);
+module_exit(wm8994_exit);
+
MODULE_DESCRIPTION("ASoC WM8994 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:wm8994-codec");
+
+//=====================================================================
+//Proc
+#ifdef WM8994_PROC
+static ssize_t wm8994_proc_write(struct file *file, const char __user *buffer,
+ unsigned long len, void *data)
+{
+ char *cookie_pot;
+ char *p;
+ int reg;
+ int value;
+
+ cookie_pot = (char *)vmalloc( len );
+ if (!cookie_pot)
+ {
+ return -ENOMEM;
+ }
+ else
+ {
+ if (copy_from_user( cookie_pot, buffer, len ))
+ return -EFAULT;
+ }
+
+ switch(cookie_pot[0])
+ {
+ case 'd':
+ case 'D':
+ debug_write_read ++;
+ debug_write_read %= 2;
+ if(debug_write_read != 0)
+ printk("Debug read and write reg on\n");
+ else
+ printk("Debug read and write reg off\n");
+ break;
+ case 'r':
+ case 'R':
+ printk("Read reg debug\n");
+ if(cookie_pot[1] ==':')
+ {
+ debug_write_read = 1;
+ strsep(&cookie_pot,":");
+ while((p=strsep(&cookie_pot,",")))
+ {
+ reg = simple_strtol(p,NULL,16);
+ value = wm8994_reg_read(wm8994_codec->control_data,reg);
+ printk("wm8994_read:0x%04x = 0x%04x",reg,value);
+ }
+ debug_write_read = 0;
+ printk("\n");
+ }
+ else
+ {
+ printk("Error Read reg debug.\n");
+ printk("For example: echo 'r:22,23,24,25'>wm8994_ts\n");
+ }
+ break;
+ case 'w':
+ case 'W':
+ printk("Write reg debug\n");
+ if(cookie_pot[1] ==':')
+ {
+ debug_write_read = 1;
+ strsep(&cookie_pot,":");
+ while((p=strsep(&cookie_pot,"=")))
+ {
+ reg = simple_strtol(p,NULL,16);
+ p=strsep(&cookie_pot,",");
+ value = simple_strtol(p,NULL,16);
+ wm8994_reg_write(wm8994_codec->control_data,reg,value);
+ printk("wm8994_write:0x%04x = 0x%04x",reg,value);
+ }
+ debug_write_read = 0;
+ printk("\n");
+ }
+ else
+ {
+ printk("Error Write reg debug.\n");
+ printk("For example: w:22=0,23=0,24=0,25=0\n");
+ }
+ break;
+ case 'p'://enable pa
+ gpio_request(RK29_PIN6_PD3, NULL);
+ gpio_direction_output(RK29_PIN6_PD3,GPIO_HIGH);
+ gpio_free(RK29_PIN6_PD3);
+ break;
+ default:
+ printk("Help for wm8994_ts .\n-->The Cmd list: \n");
+ printk("-->'d&&D' Open or Off the debug\n");
+ printk("-->'r&&R' Read reg debug,Example: echo 'r:22,23,24,25'>wm8994_ts\n");
+ printk("-->'w&&W' Write reg debug,Example: echo 'w:22=0,23=0,24=0,25=0'>wm8994_ts\n");
+ break;
+ }
+
+ return len;
+}
+static const struct file_operations wm8994_proc_fops = {
+ .owner = THIS_MODULE,
+ //.open = snd_mem_proc_open,
+ //.read = seq_read,
+//#ifdef CONFIG_PCI
+ .write = wm8994_proc_write,
+//#endif
+ //.llseek = seq_lseek,
+ //.release = single_release,
+};
+
+static int wm8994_proc_init(void)
+{
+ struct proc_dir_entry *wm8994_proc_entry;
+ wm8994_proc_entry = create_proc_entry("driver/wm8994_ts", 0777, NULL);
+ if(wm8994_proc_entry != NULL)
+ {
+ wm8994_proc_entry->write_proc = wm8994_proc_write;
+ return -1;
+ }
+ else
+ {
+ printk("create proc error !\n");
+ }
+ return 0;
+}
+
+#endif
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
- if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
- {
- DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-
- if (codec_dai->driver->ops->hw_params)
- ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai); //by Vincent
-
- return 0;
- }
-
/* set codec DAI configuration */
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
DBG("Set codec_dai slave\n");
/* set cpu DAI configuration */
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
- DBG("Set cpu_dai slave\n");
+ DBG("Set cpu_dai master\n");
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
#endif
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- DBG("Set cpu_dai master\n");
+ DBG("Set cpu_dai slave\n");
#endif
if (ret < 0)
return ret;
default:
DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
return -EINVAL;
- break;
}
- DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
-
+ DBG("Enter:%s, %d, rate=%d,pll_out = %d\n",__FUNCTION__,__LINE__,params_rate(params),pll_out);
+#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
+ ret = snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
+ if(ret < 0)
+ {
+ DBG("rk29_hw_params_wm8994:failed to set the cpu sysclk for codec side\n");
+ return ret;
+ }
ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1, pll_out, 0);
if (ret < 0) {
DBG("rk29_hw_params_wm8994:failed to set the sysclk for codec side\n");
return ret;
}
-
- snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
-
-#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
- snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
+#else if
+
#endif
return 0;
{
.name = "WM8994 I2S1",
.stream_name = "WM8994 PCM",
- .codec_name = "WM8994.0-001a",
+ .codec_name = "wm8994-codec",
.platform_name = "rockchip-audio",
.cpu_dai_name = "rk29_i2s.0",
.codec_dai_name = "wm8994-aif1",
{
.name = "WM8994 I2S2",
.stream_name = "WM8994 PCM",
- .codec_name = "WM8994.0-001a",
+ .codec_name = "wm8994-codec",
.platform_name = "rockchip-audio",
.cpu_dai_name = "rk29_i2s.0",
.codec_dai_name = "wm8994-aif2",
{
.name = "WM8994 I2S3",
.stream_name = "WM8994 PCM",
- .codec_name = "WM8994.0-001a",
+ .codec_name = "wm8994-codec",
.platform_name = "rockchip-audio",
.cpu_dai_name = "rk29_i2s.0",
.codec_dai_name = "wm8994-aif3",
static struct snd_soc_card snd_soc_card_rk29 = {
.name = "RK29_WM8994",
.dai_link = rk29_dai,
- .num_links = 3,
+ .num_links = ARRAY_SIZE(rk29_dai),
};
static struct platform_device *rk29_snd_device;