From: 邱建斌 Date: Thu, 1 Dec 2011 02:49:43 +0000 (+0800) Subject: phonesdk: update wm8994 device X-Git-Tag: firefly_0821_release~9733^2 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ae152fa3e9b777b210f8e7fd3a71f0af9a839e10;p=firefly-linux-kernel-4.4.55.git phonesdk: update wm8994 device --- diff --git a/arch/arm/mach-rk29/board-rk29-phonesdk.c b/arch/arm/mach-rk29/board-rk29-phonesdk.c index 7ff1514f212f..825489336d91 100755 --- a/arch/arm/mach-rk29/board-rk29-phonesdk.c +++ b/arch/arm/mach-rk29/board-rk29-phonesdk.c @@ -52,6 +52,9 @@ #include #include +#include +#include + #include #include #include @@ -1696,12 +1699,126 @@ struct platform_device rk29_device_gps = { }; #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, }; @@ -1906,6 +2023,9 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = { .type = "wm8994", .addr = 0x1a, .flags = 0, + #if defined(CONFIG_MFD_WM8994) + .platform_data = &wm8994_platform_data, + #endif }, #endif #if defined (CONFIG_BATTERY_STC3100) @@ -2963,6 +3083,11 @@ static struct platform_device *devices[] __initdata = { &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 @@ -3463,7 +3588,8 @@ static void __init machine_rk29_board_init(void) 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; diff --git a/drivers/headset_observe/rk_headset.c b/drivers/headset_observe/rk_headset.c index e5b6f6d178ac..ab47661ca195 100755 --- a/drivers/headset_observe/rk_headset.c +++ b/drivers/headset_observe/rk_headset.c @@ -194,7 +194,7 @@ static void headsetobserve_work(struct work_struct *work) // 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); @@ -219,11 +219,11 @@ static void headsetobserve_work(struct work_struct *work) // 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 diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c old mode 100644 new mode 100755 index 7617bcd01743..89c20f0e1c66 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -25,10 +25,12 @@ #include #include #include -#include - -#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) { @@ -46,6 +48,7 @@ static int wm8994_read(struct wm8994 *wm8994, unsigned short reg, dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n", be16_to_cpu(buf[i]), reg + i, reg + i); } + return 0; } @@ -65,7 +68,7 @@ int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg) 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 @@ -109,6 +112,7 @@ static int wm8994_write(struct wm8994 *wm8994, unsigned short reg, 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); } @@ -125,7 +129,7 @@ int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg, 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); @@ -245,13 +249,13 @@ static struct mfd_cell wm8994_devs[] = { * 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[] = { @@ -267,17 +271,18 @@ 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; } @@ -288,13 +293,13 @@ int wm8994_suspend(struct wm8994 *wm8994) 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. @@ -303,51 +308,46 @@ int wm8994_suspend(struct wm8994 *wm8994) 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; @@ -399,7 +399,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) goto err; } -/* switch (wm8994->type) { + switch (wm8994->type) { case WM8994: wm8994->num_supplies = ARRAY_SIZE(wm8994_main_supplies); break; @@ -446,7 +446,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) 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"); @@ -542,12 +542,12 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq) 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); @@ -559,10 +559,10 @@ static void wm8994_device_exit(struct wm8994 *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); } @@ -590,43 +590,38 @@ static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg, 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; @@ -642,7 +637,7 @@ int wm8994_probe(struct i2c_client *i2c, 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); @@ -650,6 +645,46 @@ int wm8994_remove(struct i2c_client *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 "); diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c old mode 100644 new mode 100755 index 383080bf9762..e7b65bbd698f --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -120,7 +120,7 @@ static struct regulator_ops wm8994_ldo1_ops = { .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, @@ -189,7 +189,7 @@ static struct regulator_ops wm8994_ldo2_ops = { .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, @@ -238,6 +238,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) 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) { diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h index 3e2c91f91657..f0b69cdae41c 100644 --- a/include/linux/mfd/wm8994/core.h +++ b/include/linux/mfd/wm8994/core.h @@ -16,7 +16,6 @@ #define __MFD_WM8994_CORE_H__ #include -#include enum wm8994_type { WM8994 = 0, @@ -114,10 +113,4 @@ static inline void wm8994_free_irq(struct wm8994 *wm8994, int irq, void *data) 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 diff --git a/include/linux/mfd/wm8994/gpio.h b/include/linux/mfd/wm8994/gpio.h index b4d4c22991e8..0c79b5ff4b5a 100644 --- a/include/linux/mfd/wm8994/gpio.h +++ b/include/linux/mfd/wm8994/gpio.h @@ -36,6 +36,10 @@ #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 */ diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 52f46b3cc58c..f7bc8d07ae40 100755 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -10,7 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define DEBUG + #include #include #include @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,10 +39,24 @@ #include "wm8994.h" #include "wm_hubs.h" +#define WM8994_PROC +#ifdef WM8994_PROC +#include +#include +#include +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, @@ -121,12 +136,17 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, 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); @@ -139,18 +159,25 @@ static unsigned int wm8994_read(struct snd_soc_codec *codec, 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) @@ -2331,32 +2358,6 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) 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 |\ @@ -2446,7 +2447,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = { }; #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; @@ -2473,20 +2474,16 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec, pm_message_t state) 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, @@ -2882,31 +2879,33 @@ out: 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) @@ -3149,7 +3148,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) } - 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) { @@ -3184,13 +3183,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) 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: @@ -3246,8 +3238,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) 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, @@ -3260,71 +3252,164 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { .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 "); 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 diff --git a/sound/soc/rk29/rk29_wm8994.c b/sound/soc/rk29/rk29_wm8994.c index 95bb3ecaff97..1bd6e5b1e0e5 100755 --- a/sound/soc/rk29/rk29_wm8994.c +++ b/sound/soc/rk29/rk29_wm8994.c @@ -46,16 +46,6 @@ static int rk29_aif1_hw_params(struct snd_pcm_substream *substream, 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"); @@ -72,14 +62,14 @@ static int rk29_aif1_hw_params(struct snd_pcm_substream *substream, /* 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; @@ -100,22 +90,23 @@ static int rk29_aif1_hw_params(struct snd_pcm_substream *substream, 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; @@ -278,7 +269,7 @@ static struct snd_soc_dai_link rk29_dai[] = { { .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", @@ -287,7 +278,7 @@ static struct snd_soc_dai_link rk29_dai[] = { { .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", @@ -296,7 +287,7 @@ static struct snd_soc_dai_link rk29_dai[] = { { .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", @@ -307,7 +298,7 @@ static struct snd_soc_dai_link rk29_dai[] = { 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;