add support rk1000 codec and tvencoder
authorhuang zhibao <hzb@rock-chips.com>
Wed, 4 Mar 2015 02:52:18 +0000 (10:52 +0800)
committerhuang zhibao <hzb@rock-chips.com>
Wed, 4 Mar 2015 02:52:18 +0000 (10:52 +0800)
16 files changed:
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/rk1000-core.c [new file with mode: 0755]
drivers/video/rockchip/tve/Kconfig
drivers/video/rockchip/tve/Makefile
drivers/video/rockchip/tve/rk1000/Kconfig [new file with mode: 0755]
drivers/video/rockchip/tve/rk1000/Makefile [new file with mode: 0755]
drivers/video/rockchip/tve/rk1000/rk1000_tve.c [new file with mode: 0755]
drivers/video/rockchip/tve/rk1000/rk1000_tve.h [new file with mode: 0755]
drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c [new file with mode: 0755]
drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c [new file with mode: 0755]
include/linux/mfd/rk1000.h [new file with mode: 0755]
sound/soc/codecs/Kconfig
sound/soc/codecs/rk1000_codec.c
sound/soc/codecs/rk1000_codec.h
sound/soc/rockchip/rk_rk1000codec.c

index e2422f44a4c1ffa3e69dd1c2619d143c3b459b48..f5d4668bd01e8279ba787a9df8e8afa02b4ccc54 100755 (executable)
@@ -1226,6 +1226,14 @@ config MFD_WM8994
          core support for the WM8994, in order to use the actual
          functionaltiy of the device other drivers must be enabled.
 
+config MFD_RK1000
+       bool "RK1000 Multimedia support"
+       depends on I2C=y && GPIOLIB
+       select MFD_CORE
+       help
+         if you say yes here you get support for the RK1000, with func as
+         TVEncoder CODEC.
+
 config MFD_RK610
        bool "RK610(Jetta) Multimedia support"
        depends on I2C=y && GPIOLIB
index ff346f12f533e36a05a34a74f91b632c48125eb8..39c29f11aa3dc0446968ea90a7df2123c52fe547 100755 (executable)
@@ -168,6 +168,7 @@ obj-$(CONFIG_MFD_LM3533)    += lm3533-core.o lm3533-ctrlbank.o
 obj-$(CONFIG_VEXPRESS_CONFIG)  += vexpress-config.o vexpress-sysreg.o
 obj-$(CONFIG_VEXPRESS_SPC)     += vexpress-spc.o
 obj-$(CONFIG_MFD_RETU)         += retu-mfd.o
+obj-$(CONFIG_MFD_RK1000)       += rk1000-core.o
 obj-$(CONFIG_MFD_RK610)        += rk610-core.o
 obj-$(CONFIG_MFD_AS3711)       += as3711.o
 obj-$(CONFIG_MFD_RK616)                += rk616-core.o rk616-vif.o
diff --git a/drivers/mfd/rk1000-core.c b/drivers/mfd/rk1000-core.c
new file mode 100755 (executable)
index 0000000..09d43d6
--- /dev/null
@@ -0,0 +1,266 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/rk1000.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+
+#define RK1000_CORE_DBG 0
+
+#if RK1000_CORE_DBG
+#define        DBG(x...)       pr_info(x)
+#else
+#define        DBG(x...)
+#endif
+
+#define        CTRL_ADC        0x00
+#define        CTRL_CODEC      0x01
+#define        CTRL_I2C        0x02
+#define        CTRL_TVE        0x03
+#define        RGB2CCIR_RESET  0x04
+#define        ADC_START       0x05
+
+struct rk1000 {
+       struct i2c_client *client;
+       struct device *dev;
+       struct dentry *debugfs_dir;
+       struct ioctrl io_power;
+       struct ioctrl io_reset;
+};
+
+static struct rk1000 *rk1000;
+
+void rk1000_reset_ctrl(int enable)
+{
+       DBG("rk1000_reset_ctrl\n");
+       if (rk1000 && gpio_is_valid(rk1000->io_reset.gpio)) {
+               if (enable) {
+                       gpio_set_value(rk1000->io_reset.gpio,
+                                      !(rk1000->io_reset.active));
+               } else {
+                       DBG("rk1000 reset pull low\n");
+                       gpio_set_value(rk1000->io_reset.gpio,
+                                      (rk1000->io_reset.active));
+               }
+       }
+}
+
+int rk1000_i2c_send(const u8 addr, const u8 reg, const u8 value)
+{
+       struct i2c_adapter *adap;
+       struct i2c_msg msg;
+       int ret;
+       char buf[2];
+
+       if (rk1000 == NULL || rk1000->client == NULL) {
+               DBG("rk1000 not init!\n");
+               return -1;
+       }
+       adap = rk1000->client->adapter;
+       buf[0] = reg;
+       buf[1] = value;
+       msg.addr = addr;
+       msg.flags = rk1000->client->flags;
+       msg.len = 2;
+       msg.buf = buf;
+       msg.scl_rate = RK1000_I2C_RATE;
+       ret = i2c_transfer(adap, &msg, 1);
+       if (ret != 1) {
+               DBG("rk1000 control i2c write err,ret =%d\n", ret);
+               return -1;
+       }
+       return 0;
+}
+
+int rk1000_i2c_recv(const u8 addr, const u8 reg, const char *buf)
+{
+       struct i2c_adapter *adap;
+       struct i2c_msg msgs[2];
+       int ret;
+
+       if (rk1000 == NULL || rk1000->client == NULL) {
+               DBG("rk1000 not init!\n");
+               return -1;
+       }
+       adap = rk1000->client->adapter;
+       msgs[0].addr = addr;
+       msgs[0].flags = rk1000->client->flags;
+       msgs[0].len = 1;
+       msgs[0].buf = (unsigned char *)(&reg);
+       msgs[0].scl_rate = RK1000_I2C_RATE;
+       msgs[1].addr = addr;
+       msgs[1].flags = rk1000->client->flags | I2C_M_RD;
+       msgs[1].len = 1;
+       msgs[1].buf = (unsigned char *)buf;
+       msgs[1].scl_rate = RK1000_I2C_RATE;
+       ret = i2c_transfer(adap, msgs, 2);
+       return (ret == 2) ? 0 : -1;
+}
+
+
+#ifdef CONFIG_PM
+static int rk1000_control_suspend(struct device *dev)
+{
+       int ret;
+
+       DBG("rk1000_control_suspend\n");
+       ret = rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_CODEC, 0x22);
+       DBG("ret=0x%x\n", ret);
+       ret = rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_TVE, 0x00);
+       DBG("ret=0x%x\n", ret);
+       ret = rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_TVE, 0x07);
+       DBG("ret=0x%x\n", ret);
+       rk1000_reset_ctrl(0);
+       return 0;
+}
+
+static int rk1000_control_resume(struct device *dev)
+{
+       int ret;
+
+       rk1000_reset_ctrl(1);
+       DBG("rk1000_control_resume\n");
+       /* ADC power off */
+       ret = rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_ADC, 0x88);
+       DBG("ret=0x%x\n", ret);
+       #ifdef CONFIG_SND_SOC_RK1000
+       ret = rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_CODEC, 0x00);
+       #else
+       ret = rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_CODEC, 0x0d);
+       #endif
+       DBG("ret=0x%x\n", ret);
+       rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_I2C, 0x22);
+       DBG("ret=0x%x\n", ret);
+       /* rk1000_codec_reg_set(); */
+       return 0;
+}
+#endif
+
+
+
+static int rk1000_probe(struct i2c_client *client,
+                       const struct i2c_device_id *id)
+{
+       struct device_node *rk1000_np;
+       enum of_gpio_flags flags;
+       int ret;
+
+       DBG("[%s] start\n", __func__);
+       rk1000 = kmalloc(sizeof(*rk1000), GFP_KERNEL);
+       if (!rk1000) {
+               dev_err(&client->dev, ">> rk1000 core inf kmalloc fail!");
+               return -ENOMEM;
+       }
+       memset(rk1000, 0, sizeof(struct rk1000));
+       rk1000->client = client;
+       rk1000->dev = &client->dev;
+       rk1000_np = rk1000->dev->of_node;
+       /********Get reset pin***********/
+       rk1000->io_reset.gpio = of_get_named_gpio_flags(rk1000_np,
+                                                       "gpio-reset",
+                                                       0, &flags);
+       if (!gpio_is_valid(rk1000->io_reset.gpio)) {
+               DBG("invalid rk1000->io_reset.gpio: %d\n",
+                   rk1000->io_reset.gpio);
+               ret = -1;
+               goto err;
+       }
+       ret = gpio_request(rk1000->io_reset.gpio, "rk1000-reset-io");
+       if (ret != 0) {
+               DBG("gpio_request rk1000->io_reset.gpio invalid: %d\n",
+                   rk1000->io_reset.gpio);
+               goto err;
+       }
+       rk1000->io_reset.active = !(flags & OF_GPIO_ACTIVE_LOW);
+       gpio_direction_output(rk1000->io_reset.gpio,
+                             !(rk1000->io_reset.active));
+       msleep(20);
+       /********Get power pin***********/
+       rk1000->io_power.gpio = of_get_named_gpio_flags(rk1000_np,
+                                                       "gpio-power",
+                                                       0, &flags);
+       if (gpio_is_valid(rk1000->io_power.gpio)) {
+               ret = gpio_request(rk1000->io_power.gpio, "rk1000-power-io");
+               if (ret != 0) {
+                       DBG("gpio_request rk1000->io_power.gpio invalid: %d\n",
+                           rk1000->io_power.gpio);
+                       goto err;
+               }
+               rk1000->io_power.active = !(flags & OF_GPIO_ACTIVE_LOW);
+               gpio_direction_output(rk1000->io_power.gpio,
+                                     rk1000->io_power.active);
+       }
+       /********rk1000 reset***********/
+       gpio_set_value(rk1000->io_reset.gpio, rk1000->io_reset.active);
+       msleep(100);
+       gpio_set_value(rk1000->io_reset.gpio, !(rk1000->io_reset.active));
+       rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_ADC, 0x88);
+       #ifdef CONFIG_SND_SOC_RK1000
+       rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_CODEC, 0x00);
+       #else
+       rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_CODEC, 0x0d);
+       #endif
+       rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_I2C, 0x22);
+       rk1000_i2c_send(I2C_ADDR_CTRL, CTRL_TVE, 0x00);
+       DBG("rk1000 probe ok\n");
+       return 0;
+err:
+       kfree(rk1000);
+       rk1000 = NULL;
+       return ret;
+}
+
+static int rk1000_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+static const struct i2c_device_id rk1000_id[] = {
+       { "rk1000_control", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rk1000_id);
+
+static const struct dev_pm_ops rockchip_rk1000_pm_ops = {
+       .suspend_late = rk1000_control_suspend,
+       .resume_early = rk1000_control_resume,
+};
+
+static struct i2c_driver rk1000_driver = {
+       .driver = {
+               .name = "rk1000_control",
+               #ifdef CONFIG_PM
+               .pm     = &rockchip_rk1000_pm_ops,
+               #endif
+       },
+       .probe = rk1000_probe,
+       .remove = rk1000_remove,
+       .id_table = rk1000_id,
+};
+
+
+static int __init rk1000_init(void)
+{
+       return i2c_add_driver(&rk1000_driver);
+}
+
+static void __exit rk1000_exit(void)
+{
+       i2c_del_driver(&rk1000_driver);
+}
+
+fs_initcall_sync(rk1000_init);
+module_exit(rk1000_exit);
+
+
+MODULE_DESCRIPTION("RK1000 control driver");
+MODULE_AUTHOR("Rock-chips, <www.rock-chips.com>");
+MODULE_LICENSE("GPL");
index e165ee3250ef6f1d5b7943bfeaf040bb4330a37c..83c2c0e58a38bddc90b0f51d456d6e7ccda86bff 100644 (file)
@@ -8,6 +8,7 @@ menuconfig RK_TVENCODER
        help
                Support RockChip TV Encoder if you say y here.
 
+source "drivers/video/rockchip/tve/rk1000/Kconfig"
 source "drivers/video/rockchip/tve/rk3036/Kconfig"
 source "drivers/video/rockchip/tve/rk610/Kconfig"
 
index ea651687c417dfbfaeb287163db85b305ccd98bd..ae38690889fd2de24bd46de7c5769124fc239160 100644 (file)
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_RK610_TVOUT)              += rk610/
 obj-$(CONFIG_RK3036_TV_ENCODER)                += rk3036/
+obj-$(CONFIG_RK1000_TVOUT)             += rk1000/
diff --git a/drivers/video/rockchip/tve/rk1000/Kconfig b/drivers/video/rockchip/tve/rk1000/Kconfig
new file mode 100755 (executable)
index 0000000..a708973
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# TV Encoder RK1000 drivers configuration
+#
+
+config RK1000_TVOUT
+       bool "RK1000 TV Encoder support"
+       depends on RK_TVENCODER
+       select MFD_RK1000
+       help
+               Support rk1000 to output YPbPr and CVBS.
+               
+config RK1000_TVOUT_YPbPr
+       bool "Support YPbPr Output"
+       depends on RK1000_TVOUT
+config RK1000_TVOUT_CVBS
+       bool "Support CVBS Output"
+       depends on RK1000_TVOUT
+
diff --git a/drivers/video/rockchip/tve/rk1000/Makefile b/drivers/video/rockchip/tve/rk1000/Makefile
new file mode 100755 (executable)
index 0000000..d229b49
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the RK1000 tv control.
+#
+obj-$(CONFIG_RK1000_TVOUT)             += rk1000_tve.o
+obj-$(CONFIG_RK1000_TVOUT_YPbPr)       += rk1000_tve_ypbpr.o
+obj-$(CONFIG_RK1000_TVOUT_CVBS)                += rk1000_tve_cvbs.o
diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve.c b/drivers/video/rockchip/tve/rk1000/rk1000_tve.c
new file mode 100755 (executable)
index 0000000..483ae03
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * rk1000_tv.c
+ *
+ * Driver for rockchip rk1000 tv control
+ *  Copyright (C) 2009
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/fb.h>
+#include <linux/rk_fb.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <dt-bindings/rkfb/rk_fb.h>
+#endif
+#include "rk1000_tve.h"
+
+struct rk1000_tve rk1000_tve;
+
+
+int rk1000_tv_write_block(u8 reg, u8 *buf, u8 len)
+{
+       int i, ret;
+
+       for (i = 0; i < len; i++) {
+               ret = rk1000_i2c_send(I2C_ADDR_TVE, reg + i, buf[i]);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
+
+int rk1000_control_write_block(u8 reg, u8 *buf, u8 len)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < len; i++) {
+               ret = rk1000_i2c_send(I2C_ADDR_CTRL, reg + i, buf[i]);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
+
+int rk1000_switch_fb(const struct fb_videomode *modedb, int tv_mode)
+{
+       struct rk_screen *screen;
+
+       if (modedb == NULL)
+               return -1;
+       screen =  kzalloc(sizeof(*screen), GFP_KERNEL);
+       if (screen == NULL)
+               return -1;
+       memset(screen, 0, sizeof(*screen));
+       /* screen type & face */
+       screen->type = SCREEN_RGB;
+       screen->face = OUT_P888;
+       screen->mode = *modedb;
+       screen->mode.vmode = 0;
+       /* Pin polarity */
+       if (FB_SYNC_HOR_HIGH_ACT & modedb->sync)
+               screen->pin_hsync = 1;
+       else
+               screen->pin_hsync = 0;
+       if (FB_SYNC_VERT_HIGH_ACT & modedb->sync)
+               screen->pin_vsync = 1;
+       else
+               screen->pin_vsync = 0;
+       screen->pin_den = 0;
+       screen->pin_dclk = 1;
+       /* Swap rule */
+       screen->swap_rb = 0;
+       screen->swap_rg = 0;
+       screen->swap_gb = 0;
+       screen->swap_delta = 0;
+       screen->swap_dumy = 0;
+       screen->overscan.left = 95;
+       screen->overscan.top = 95;
+       screen->overscan.right = 95;
+       screen->overscan.bottom = 95;
+       /* Operation function*/
+       screen->init = NULL;
+       screen->standby = NULL;
+       switch (tv_mode) {
+       #ifdef CONFIG_RK1000_TVOUT_CVBS
+       case TVOUT_CVBS_NTSC:
+               screen->init = rk1000_tv_ntsc_init;
+       break;
+       case TVOUT_CVBS_PAL:
+               screen->init = rk1000_tv_pal_init;
+       break;
+       #endif
+       #ifdef CONFIG_RK1000_TVOUT_YPBPR
+       case TVOUT_YPBPR_720X480P_60:
+               screen->init = rk1000_tv_ypbpr480_init;
+       break;
+       case TVOUT_YPBPR_720X576P_50:
+               screen->init = rk1000_tv_ypbpr576_init;
+       break;
+       case TVOUT_YPBPR_1280X720P_50:
+               screen->init = rk1000_tv_ypbpr720_50_init;
+       break;
+       case TVOUT_YPBPR_1280X720P_60:
+               screen->init = rk1000_tv_ypbpr720_60_init;
+       break;
+       #endif
+       default:
+               kfree(screen);
+               return -1;
+       }
+       rk_fb_switch_screen(screen, 1 , rk1000_tve.video_source);
+       rk1000_tve.mode = tv_mode;
+       kfree(screen);
+       if (gpio_is_valid(rk1000_tve.io_switch.gpio)) {
+               if (tv_mode < TVOUT_YPBPR_720X480P_60)
+                       gpio_direction_output(rk1000_tve.io_switch.gpio,
+                                             !(rk1000_tve.io_switch.active));
+               else
+                       gpio_direction_output(rk1000_tve.io_switch.gpio,
+                                             rk1000_tve.io_switch.active);
+       }
+       return 0;
+}
+
+int rk1000_tv_standby(int type)
+{
+       unsigned char val;
+       int ret;
+       int ypbpr;
+       int cvbs;
+       struct rk_screen screen;
+
+       ypbpr = 0;
+       cvbs = 0;
+       if (rk1000_tve.ypbpr)
+               ypbpr = rk1000_tve.ypbpr->enable;
+       if (rk1000_tve.cvbs)
+               cvbs = rk1000_tve.cvbs->enable;
+       if (cvbs || ypbpr)
+               return 0;
+       val = 0x00;
+       ret = rk1000_control_write_block(0x03, &val, 1);
+       if (ret < 0) {
+               pr_err("rk1000_control_write_block err!\n");
+               return ret;
+       }
+       val = 0x07;
+       ret = rk1000_tv_write_block(0x03, &val, 1);
+       if (ret < 0) {
+               pr_err("rk1000_tv_write_block err!\n");
+               return ret;
+       }
+       screen.type = SCREEN_RGB;
+       rk_fb_switch_screen(&screen, 0 , rk1000_tve.video_source);
+       pr_err("rk1000 tve standby\n");
+       return 0;
+}
+
+static int rk1000_tve_initial(void)
+{
+       struct rk_screen screen;
+
+       /* RK1000 tvencoder i2c reg need dclk, so we open lcdc.*/
+       memset(&screen, 0, sizeof(struct rk_screen));
+       /* screen type & face */
+       screen.type = SCREEN_RGB;
+       screen.face = OUT_P888;
+       /* Screen size */
+       screen.mode.xres = 720;
+       screen.mode.yres = 480;
+       /* Timing */
+       screen.mode.pixclock = 27000000;
+       screen.mode.refresh = 60;
+       screen.mode.left_margin = 116;
+       screen.mode.right_margin = 16;
+       screen.mode.hsync_len = 6;
+       screen.mode.upper_margin = 25;
+       screen.mode.lower_margin = 14;
+       screen.mode.vsync_len = 6;
+       rk_fb_switch_screen(&screen, 2 , rk1000_tve.video_source);
+       /* Power down RK1000 output DAC. */
+       return rk1000_i2c_send(I2C_ADDR_TVE, 0x03, 0x07);
+}
+
+
+static void rk1000_early_suspend(void *h)
+{
+       pr_info("rk1000_early_suspend\n");
+       if (rk1000_tve.ypbpr) {
+               rk1000_tve.ypbpr->ddev->ops->setenable(rk1000_tve.ypbpr->ddev,
+                                                      0);
+               rk1000_tve.ypbpr->suspend = 1;
+       }
+       if (rk1000_tve.cvbs) {
+               rk1000_tve.cvbs->ddev->ops->setenable(rk1000_tve.cvbs->ddev,
+                                                     0);
+               rk1000_tve.cvbs->suspend = 1;
+       }
+}
+
+
+static void rk1000_early_resume(void *h)
+{
+       pr_info("rk1000 tve exit early resume\n");
+       if (rk1000_tve.cvbs) {
+               rk1000_tve.cvbs->suspend = 0;
+               if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60)
+                       rk_display_device_enable((rk1000_tve.cvbs)->ddev);
+       }
+       if (rk1000_tve.ypbpr) {
+               rk1000_tve.ypbpr->suspend = 0;
+               if (rk1000_tve.mode > TVOUT_CVBS_PAL)
+                       rk_display_device_enable((rk1000_tve.ypbpr)->ddev);
+       }
+}
+
+
+static int rk1000_fb_event_notify(struct notifier_block *self,
+                                 unsigned long action, void *data)
+{
+       struct fb_event *event;
+       int blank_mode;
+
+       event = data;
+       blank_mode = *((int *)event->data);
+       if (action == FB_EARLY_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+               break;
+               default:
+               rk1000_early_suspend(NULL);
+               break;
+               }
+       } else if (action == FB_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       rk1000_early_resume(NULL);
+               break;
+               default:
+               break;
+               }
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block rk1000_fb_notifier = {
+       .notifier_call = rk1000_fb_event_notify,
+};
+
+static int rk1000_tve_probe(struct i2c_client *client,
+                           const struct i2c_device_id *id)
+{
+       struct device_node *tve_np;
+       enum of_gpio_flags flags;
+       int rc;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               rc = -ENODEV;
+               goto failout;
+       }
+
+       memset(&rk1000_tve, 0, sizeof(struct rk1000_tve));
+       rk1000_tve.client = client;
+#ifdef CONFIG_OF
+       tve_np = client->dev.of_node;
+       rk1000_tve.io_switch.gpio = of_get_named_gpio_flags(tve_np,
+                                                           "gpio-reset",
+                                                           0, &flags);
+       if (gpio_is_valid(rk1000_tve.io_switch.gpio)) {
+               rc = gpio_request(rk1000_tve.io_switch.gpio,
+                                 "rk1000-tve-swicth-io");
+               if (!rc) {
+                       rk1000_tve.io_switch.active = !(flags &
+                                                       OF_GPIO_ACTIVE_LOW);
+                       gpio_direction_output(rk1000_tve.io_switch.gpio,
+                                             !(rk1000_tve.io_switch.active));
+               } else
+                       pr_err("gpio request rk1000-tve-swicth-io err: %d\n",
+                              rk1000_tve.io_switch.gpio);
+       }
+       of_property_read_u32(tve_np, "rockchip,source", &(rc));
+       rk1000_tve.video_source = rc;
+       of_property_read_u32(tve_np, "rockchip,prop", &(rc));
+       rk1000_tve.property = rc - 1;
+       pr_err("video src is lcdc%d, prop is %d\n", rk1000_tve.video_source,
+              rk1000_tve.property);
+#endif
+       rk1000_tve.mode = RK1000_TVOUT_DEAULT;
+       rc = rk1000_tve_initial();
+       if (rc) {
+               dev_err(&client->dev, "rk1000 tvencoder probe error %d\n", rc);
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_RK1000_TVOUT_YPBPR
+       rk1000_register_display_ypbpr(&client->dev);
+#endif
+
+#ifdef CONFIG_RK1000_TVOUT_CVBS
+       rk1000_register_display_cvbs(&client->dev);
+#endif
+       #ifdef CONFIG_HAS_EARLYSUSPEND
+       rk1000_tve.early_suspend.suspend = rk1000_early_suspend;
+       rk1000_tve.early_suspend.resume = rk1000_early_resume;
+       rk1000_tve.early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 11;
+       register_early_suspend(&(rk1000_tve.early_suspend));
+       #endif
+       fb_register_client(&rk1000_fb_notifier);
+       pr_info("rk1000 tvencoder ver 2.0 probe ok\n");
+       return 0;
+failout:
+       kfree(client);
+       client = NULL;
+       return rc;
+}
+
+static int rk1000_tve_remove(struct i2c_client *client)
+{
+       return 0;
+}
+
+static void rk1000_tve_shutdown(struct i2c_client *client)
+{
+       rk1000_i2c_send(I2C_ADDR_TVE, 0x03, 0x07);
+}
+
+static const struct i2c_device_id rk1000_tve_id[] = {
+       { "rk1000_tve", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rk1000_tve_id);
+
+static struct i2c_driver rk1000_tve_driver = {
+       .driver         = {
+               .name   = "rk1000_tve",
+       },
+       .id_table = rk1000_tve_id,
+       .probe = rk1000_tve_probe,
+       .remove = rk1000_tve_remove,
+       .shutdown = rk1000_tve_shutdown,
+};
+
+static int __init rk1000_tve_init(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&rk1000_tve_driver);
+       if (ret < 0)
+               pr_err("i2c_add_driver err, ret = %d\n", ret);
+       return ret;
+}
+
+static void __exit rk1000_tve_exit(void)
+{
+       i2c_del_driver(&rk1000_tve_driver);
+}
+
+late_initcall(rk1000_tve_init);
+module_exit(rk1000_tve_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("ROCKCHIP rk1000 TV Encoder ");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve.h b/drivers/video/rockchip/tve/rk1000/rk1000_tve.h
new file mode 100755 (executable)
index 0000000..996506f
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _RK1000_TVE_H
+#define _RK1000_TVE_H
+#include <linux/fb.h>
+#include <linux/rk_fb.h>
+#include <linux/display-sys.h>
+#include <linux/mfd/rk1000.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+/******************* TVOUT OUTPUT TYPE **********************/
+struct rk1000_monspecs {
+       struct rk_display_device *ddev;
+       unsigned int enable;
+       unsigned int suspend;
+       struct fb_videomode *mode;
+       struct list_head modelist;
+       unsigned int mode_set;
+};
+
+struct rk1000_tve {
+       struct device *dev;
+       struct i2c_client *client;
+       #ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend early_suspend;
+       #endif
+       struct ioctrl io_switch;
+       int video_source;
+       int property;
+       int mode;
+       struct rk1000_monspecs *cvbs;
+       struct rk1000_monspecs *ypbpr;
+};
+
+extern struct rk1000_tve rk1000_tve;
+
+enum {
+       TVOUT_CVBS_NTSC = 1,
+       TVOUT_CVBS_PAL,
+       TVOUT_YPBPR_720X480P_60,
+       TVOUT_YPBPR_720X576P_50,
+       TVOUT_YPBPR_1280X720P_50,
+       TVOUT_YPBPR_1280X720P_60
+};
+
+enum {
+       RK1000_TVOUT_CVBS = 0,
+       RK1000_TVOUT_YC,
+       RK1000_TVOUT_YPBPR,
+};
+#ifdef CONFIG_RK1000_TVOUT_CVBS
+#define RK1000_TVOUT_DEAULT TVOUT_CVBS_NTSC
+#else
+#define RK1000_TVOUT_DEAULT TVOUT_YPBPR_1280X720P_60
+#endif
+
+int rk1000_control_write_block(u8 reg, u8 *buf, u8 len);
+int rk1000_tv_write_block(u8 reg, u8 *buf, u8 len);
+int rk1000_tv_standby(int type);
+int rk1000_switch_fb(const struct fb_videomode *modedb, int tv_mode);
+int rk1000_register_display(struct device *parent);
+
+#ifdef CONFIG_RK1000_TVOUT_YPBPR
+int rk1000_tv_ypbpr480_init(void);
+int rk1000_tv_ypbpr576_init(void);
+int rk1000_tv_ypbpr720_50_init(void);
+int rk1000_tv_ypbpr720_60_init(void);
+int rk1000_register_display_ypbpr(struct device *parent);
+#endif
+
+#ifdef CONFIG_RK1000_TVOUT_CVBS
+int rk1000_tv_ntsc_init(void);
+int rk1000_tv_pal_init(void);
+int rk1000_register_display_cvbs(struct device *parent);
+#endif
+
+#endif
+
diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c b/drivers/video/rockchip/tve/rk1000/rk1000_tve_cvbs.c
new file mode 100755 (executable)
index 0000000..4e4e503
--- /dev/null
@@ -0,0 +1,182 @@
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include "rk1000_tve.h"
+
+
+
+static const struct fb_videomode rk1000_cvbs_mode[] = {
+       {"NTSC", 60, 720, 480, 27000000, 116, 16, 25, 14, 6, 6, 0, 1, 0},
+       {"PAL", 50, 720, 576, 27000000, 126, 12, 37, 6, 6, 6, 0, 1, 0},
+};
+
+static struct rk1000_monspecs cvbs_monspecs;
+
+int rk1000_tv_ntsc_init(void)
+{
+       unsigned char tv_encoder_regs[] = {0x00, 0x00, 0x00, 0x03, 0x00, 0x00};
+       unsigned char tv_encoder_control_regs[] = {0x43, 0x01};
+       int i;
+       int ret;
+
+       for (i = 0; i < sizeof(tv_encoder_regs); i++) {
+               ret = rk1000_tv_write_block(i, tv_encoder_regs + i, 1);
+               if (ret < 0) {
+                       pr_err("rk1000_tv_write_block err!\n");
+                       return ret;
+               }
+       }
+
+       for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
+               ret = rk1000_control_write_block(i + 3,
+                                                tv_encoder_control_regs + i,
+                                                1);
+               if (ret < 0) {
+                       pr_err("rk1000_control_write_block err!\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+int rk1000_tv_pal_init(void)
+{
+       unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x00, 0x03, 0x00, 0x00};
+       unsigned char tv_encoder_control_regs[] = {0x41, 0x01};
+       int i;
+       int ret;
+
+       for (i = 0; i < sizeof(tv_encoder_regs); i++) {
+               ret = rk1000_tv_write_block(i, tv_encoder_regs+i, 1);
+               if (ret < 0) {
+                       pr_err("rk1000_tv_write_block err!\n");
+                       return ret;
+               }
+       }
+
+       for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
+               ret = rk1000_control_write_block(i + 3,
+                                                tv_encoder_control_regs + i,
+                                                1);
+               if (ret < 0) {
+                       pr_err("rk1000_control_write_block err!\n");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+static int rk1000_cvbs_set_enable(struct rk_display_device *device, int enable)
+{
+       if (cvbs_monspecs.suspend)
+               return 0;
+       if ((cvbs_monspecs.enable != enable) ||
+           (cvbs_monspecs.mode_set != rk1000_tve.mode)) {
+               if ((enable == 0) && cvbs_monspecs.enable) {
+                       cvbs_monspecs.enable = 0;
+                       rk1000_tv_standby(RK1000_TVOUT_CVBS);
+               } else if (enable == 1) {
+                       rk1000_switch_fb(cvbs_monspecs.mode,
+                                        cvbs_monspecs.mode_set);
+                       cvbs_monspecs.enable = 1;
+               }
+       }
+       return 0;
+}
+
+static int rk1000_cvbs_get_enable(struct rk_display_device *device)
+{
+       return cvbs_monspecs.enable;
+}
+
+static int rk1000_cvbs_get_status(struct rk_display_device *device)
+{
+       if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60)
+               return 1;
+       else
+               return 0;
+}
+
+static int rk1000_cvbs_get_modelist(struct rk_display_device *device,
+                                   struct list_head **modelist)
+{
+       *modelist = &(cvbs_monspecs.modelist);
+       return 0;
+}
+
+static int rk1000_cvbs_set_mode(struct rk_display_device *device,
+                               struct fb_videomode *mode)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(rk1000_cvbs_mode); i++) {
+               if (fb_mode_is_equal(&rk1000_cvbs_mode[i], mode)) {
+                       if (((i + 1) != rk1000_tve.mode)) {
+                               cvbs_monspecs.mode_set = i + 1;
+                               cvbs_monspecs.mode = (struct fb_videomode *)
+                                                       &rk1000_cvbs_mode[i];
+                       }
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+static int rk1000_cvbs_get_mode(struct rk_display_device *device,
+                               struct fb_videomode *mode)
+{
+       *mode = *(cvbs_monspecs.mode);
+       return 0;
+}
+
+static struct rk_display_ops rk1000_cvbs_display_ops = {
+       .setenable = rk1000_cvbs_set_enable,
+       .getenable = rk1000_cvbs_get_enable,
+       .getstatus = rk1000_cvbs_get_status,
+       .getmodelist = rk1000_cvbs_get_modelist,
+       .setmode = rk1000_cvbs_set_mode,
+       .getmode = rk1000_cvbs_get_mode,
+};
+
+static int rk1000_display_cvbs_probe(struct rk_display_device *device,
+                                    void *devdata)
+{
+       device->owner = THIS_MODULE;
+       strcpy(device->type, "TV");
+       device->name = "cvbs";
+       device->priority = DISPLAY_PRIORITY_TV;
+       device->property = rk1000_tve.property;
+       device->priv_data = devdata;
+       device->ops = &rk1000_cvbs_display_ops;
+       return 1;
+}
+
+static struct rk_display_driver display_rk1000_cvbs = {
+       .probe = rk1000_display_cvbs_probe,
+};
+
+int rk1000_register_display_cvbs(struct device *parent)
+{
+       int i;
+
+       memset(&cvbs_monspecs, 0, sizeof(struct rk1000_monspecs));
+       INIT_LIST_HEAD(&cvbs_monspecs.modelist);
+       for (i = 0; i < ARRAY_SIZE(rk1000_cvbs_mode); i++)
+               display_add_videomode(&rk1000_cvbs_mode[i],
+                                     &cvbs_monspecs.modelist);
+       if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60) {
+               cvbs_monspecs.mode = (struct fb_videomode *)
+                                     &(rk1000_cvbs_mode[rk1000_tve.mode - 1]);
+               cvbs_monspecs.mode_set = rk1000_tve.mode;
+       } else {
+               cvbs_monspecs.mode = (struct fb_videomode *)
+                                       &(rk1000_cvbs_mode[0]);
+               cvbs_monspecs.mode_set = TVOUT_CVBS_NTSC;
+       }
+       cvbs_monspecs.ddev = rk_display_device_register(&display_rk1000_cvbs,
+                                                       parent, NULL);
+       rk1000_tve.cvbs = &cvbs_monspecs;
+       if (rk1000_tve.mode < TVOUT_YPBPR_720X480P_60)
+               rk_display_device_enable(cvbs_monspecs.ddev);
+       return 0;
+}
diff --git a/drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c b/drivers/video/rockchip/tve/rk1000/rk1000_tve_ypbpr.c
new file mode 100755 (executable)
index 0000000..dcaa5bc
--- /dev/null
@@ -0,0 +1,239 @@
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include "rk1000_tve.h"
+
+static const struct fb_videomode rk1000_ypbpr_mode[] = {
+       {"YPBPR480P", 60, 720, 480, 27000000, 70, 6, 30, 9, 62, 6, 0, 0, 0},
+       {"YPBPR576P", 50, 720, 576, 27000000, 74, 6, 39, 5, 64, 5, 0, 0, 0},
+       {"YPBPR720P@50", 50, 1280, 720, 74250000, 660, 0, 20, 5, 40,
+        5, 0, 0, 0},
+       {"YPbPR720P@60", 60, 1280, 720, 74250000, 330, 0, 20, 5, 40,
+        5, 0, 0, 0},
+};
+
+static struct rk1000_monspecs ypbpr_monspecs;
+
+int rk1000_tv_ypbpr480_init(void)
+{
+       unsigned char tv_encoder_regs[] = {0x00, 0x00, 0x40, 0x08, 0x00,
+                                          0x02, 0x17, 0x0A, 0x0A};
+       unsigned char tv_encoder_control_regs[] = {0x00};
+       int i;
+       int ret;
+
+       for (i = 0; i < sizeof(tv_encoder_regs); i++) {
+               ret = rk1000_tv_write_block(i, tv_encoder_regs + i, 1);
+               if (ret < 0) {
+                       prr_err("rk1000_tv_write_block err!\n");
+                       return ret;
+               }
+       }
+       for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
+               ret = rk1000_control_write_block(i+3,
+                                                tv_encoder_control_regs+i,
+                                                1);
+               if (ret < 0) {
+                       prr_err("rk1000_control_write_block err!\n");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+int rk1000_tv_ypbpr576_init(void)
+{
+       unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x40, 0x08, 0x00,
+                                          0x01, 0x17, 0x0A, 0x0A};
+       unsigned char tv_encoder_control_regs[] = {0x00};
+       int i;
+       int ret;
+
+       for (i = 0; i < sizeof(tv_encoder_regs); i++) {
+               ret = rk1000_tv_write_block(i, tv_encoder_regs+i, 1);
+               if (ret < 0) {
+                       prr_err("rk1000_tv_write_block err!\n");
+                       return ret;
+               }
+       }
+       for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
+               ret = rk1000_control_write_block(i + 3,
+                                                tv_encoder_control_regs + i,
+                                                1);
+               if (ret < 0) {
+                       prr_err("rk1000_control_write_block err!\n");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+int rk1000_tv_ypbpr720_50_init(void)
+{
+       unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x40, 0x08,
+                                          0x00, 0x13, 0x17, 0x0A, 0x0A};
+       unsigned char tv_encoder_control_regs[] = {0x00};
+       int i;
+       int ret;
+
+       for (i = 0; i < sizeof(tv_encoder_regs); i++) {
+               ret = rk1000_tv_write_block(i, tv_encoder_regs+i, 1);
+               if (ret < 0) {
+                       prr_err("rk1000_tv_write_block err!\n");
+                       return ret;
+               }
+       }
+
+       for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
+               ret = rk1000_control_write_block(i+3,
+                                                tv_encoder_control_regs+i,
+                                                1);
+               if (ret < 0) {
+                       prr_err("rk1000_control_write_block err!\n");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+int rk1000_tv_ypbpr720_60_init(void)
+{
+       unsigned char tv_encoder_regs[] = {0x06, 0x00, 0x40, 0x08, 0x00,
+                                          0x17, 0x17, 0x0A, 0x0A};
+       unsigned char tv_encoder_control_regs[] = {0x00};
+       int i;
+       int ret;
+
+       for (i = 0; i < sizeof(tv_encoder_regs); i++) {
+               ret = rk1000_tv_write_block(i, tv_encoder_regs + i, 1);
+               if (ret < 0) {
+                       prr_err("rk1000_tv_write_block err!\n");
+                       return ret;
+               }
+       }
+       for (i = 0; i < sizeof(tv_encoder_control_regs); i++) {
+               ret = rk1000_control_write_block(i + 3,
+                                                tv_encoder_control_regs + i,
+                                                1);
+               if (ret < 0) {
+                       prr_err("rk1000_control_write_block err!\n");
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+static int rk1000_ypbpr_set_enable(struct rk_display_device *device,
+                                  int enable)
+{
+       if (ypbpr_monspecs.suspend)
+               return 0;
+       if (ypbpr_monspecs.enable != enable ||
+           ypbpr_monspecs.mode_set != rk1000_tve.mode) {
+               if (enable == 0 && ypbpr_monspecs.enable) {
+                       ypbpr_monspecs.enable = 0;
+                       rk1000_tv_standby(RK1000_TVOUT_YPBPR);
+               } else if (enable == 1) {
+                       rk1000_switch_fb(ypbpr_monspecs.mode,
+                                        ypbpr_monspecs.mode_set);
+                       ypbpr_monspecs.enable = 1;
+               }
+       }
+       return 0;
+}
+
+static int rk1000_ypbpr_get_enable(struct rk_display_device *device)
+{
+       return ypbpr_monspecs.enable;
+}
+
+static int rk1000_ypbpr_get_status(struct rk_display_device *device)
+{
+       if (rk1000_tve.mode > TVOUT_CVBS_PAL)
+               return 1;
+       else
+               return 0;
+}
+
+static int rk1000_ypbpr_get_modelist(struct rk_display_device *device,
+                                    struct list_head **modelist)
+{
+       *modelist = &(ypbpr_monspecs.modelist);
+       return 0;
+}
+
+static int rk1000_ypbpr_set_mode(struct rk_display_device *device,
+                                struct fb_videomode *mode)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(rk1000_ypbpr_mode); i++) {
+               if (fb_mode_is_equal(&rk1000_ypbpr_mode[i], mode)) {
+                       if ((i + 3) != rk1000_tve.mode) {
+                               ypbpr_monspecs.mode_set = i + 3;
+                               ypbpr_monspecs.mode = (struct fb_videomode *)
+                                                       &rk1000_ypbpr_mode[i];
+                       }
+                       return 0;
+               }
+       }
+       return -1;
+}
+
+static int rk1000_ypbpr_get_mode(struct rk_display_device *device,
+                                struct fb_videomode *mode)
+{
+       *mode = *(ypbpr_monspecs.mode);
+       return 0;
+}
+
+static struct rk_display_ops rk1000_ypbpr_display_ops = {
+       .setenable = rk1000_ypbpr_set_enable,
+       .getenable = rk1000_ypbpr_get_enable,
+       .getstatus = rk1000_ypbpr_get_status,
+       .getmodelist = rk1000_ypbpr_get_modelist,
+       .setmode = rk1000_ypbpr_set_mode,
+       .getmode = rk1000_ypbpr_get_mode,
+};
+
+static int rk1000_display_ypbpr_probe(struct rk_display_device *device,
+                                     void *devdata)
+{
+       device->owner = THIS_MODULE;
+       strcpy(device->type, "YPbPr");
+       device->name = "ypbpr";
+       device->priority = DISPLAY_PRIORITY_YPBPR;
+       device->property = rk1000_tve.property;
+       device->priv_data = devdata;
+       device->ops = &rk1000_ypbpr_display_ops;
+       return 1;
+}
+
+static struct rk_display_driver display_rk1000_ypbpr = {
+       .probe = rk1000_display_ypbpr_probe,
+};
+
+int rk1000_register_display_ypbpr(struct device *parent)
+{
+       int i;
+
+       memset(&ypbpr_monspecs, 0, sizeof(struct rk1000_monspecs));
+       INIT_LIST_HEAD(&ypbpr_monspecs.modelist);
+       for (i = 0; i < ARRAY_SIZE(rk1000_ypbpr_mode); i++)
+               display_add_videomode(&rk1000_ypbpr_mode[i],
+                                     &ypbpr_monspecs.modelist);
+       if (rk1000_tve.mode > TVOUT_CVBS_PAL) {
+               ypbpr_monspecs.mode = (struct fb_videomode *)
+                                    &(rk1000_ypbpr_mode[rk1000_tve.mode - 3]);
+               ypbpr_monspecs.mode_set = rk1000_tve.mode;
+       } else {
+               ypbpr_monspecs.mode = (struct fb_videomode *)
+                                       &(rk1000_ypbpr_mode[3]);
+               ypbpr_monspecs.mode_set = TVOUT_YPBPR_1280X720P_60;
+       }
+       ypbpr_monspecs.ddev = rk_display_device_register(&display_rk1000_ypbpr,
+                                                        parent, NULL);
+       rk1000_tve.ypbpr = &ypbpr_monspecs;
+       if (rk1000_tve.mode > TVOUT_CVBS_PAL)
+               rk_display_device_enable(ypbpr_monspecs.ddev);
+       return 0;
+}
diff --git a/include/linux/mfd/rk1000.h b/include/linux/mfd/rk1000.h
new file mode 100755 (executable)
index 0000000..606820d
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __RK1000_H__
+#define __RK1000_H__
+
+#define I2C_ADDR_CTRL 0x40
+#define I2C_ADDR_TVE 0x42
+
+#define RK1000_I2C_RATE        (100*1000)
+
+struct ioctrl {
+       int gpio;
+       int active;
+};
+
+int rk1000_i2c_send(const u8 addr, const u8 reg, const u8 value);
+int rk1000_i2c_recv(const u8 addr, const u8 reg, const char *buf);
+
+#endif
index b7ef0b9655c30307ef51044a5cfcb0af19634f55..ac376f69ad8e3b0475b0e91730151fa4201dce87 100644 (file)
@@ -119,6 +119,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_RT5512 if I2C
        select SND_SOC_RK610 if I2C
        select SND_SOC_RK616 if I2C
+       select SND_SOC_RK1000 if I2C
        select SND_SOC_WM8903 if I2C && GENERIC_HARDIRQS
        select SND_SOC_WM8904 if I2C
        select SND_SOC_WM8940 if I2C
@@ -586,6 +587,10 @@ config SND_SOC_RK616
        tristate
        depends on MFD_RK616
 
+config SND_SOC_RK1000
+       tristate
+       depends on MFD_RK1000
+
 config SND_SOC_RK2928
        tristate
        depends on ARCH_RK2928
index a3c43c4a341302990979a2cbe2b212489a004d6c..bd979cd255a48e522e8eefa6d7e3a72c7dd86fda 100755 (executable)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
+#include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
 #include <sound/core.h>
-#include <sound/jack.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/soc-dapm.h>
 #include <sound/initval.h>
-#include <sound/tlv.h>
-#include <trace/events/asoc.h>
-
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include "rk1000_codec.h"
-//#define RK1000_CODEC_PROC
-#ifdef RK1000_CODEC_PROC
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/vmalloc.h>
-char debug_write_read = 0;
-#endif
+
+
 /*
  * Debug
  */
-#if 1
-#define        DBG(x...)       printk(KERN_INFO x)
+#define RK1000_CODEC_DBG 0
+#if RK1000_CODEC_DBG
+#define        DBG(x...)       pr_info(x)
 #else
 #define        DBG(x...)
 #endif
 
-#define err(format, arg...) \
-       printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) \
-       printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
-       
-#define OUT_CAPLESS  (0)   //ÊÇ·ñΪÎÞµçÈÝÊä³ö£¬1:ÎÞµçÈÝÊä³ö£¬0:ÓеçÈÝÊä³ö      
+/*rk1000 codec proc debug*/
+#define RK1000_CODEC_PROC 1
 
-static struct snd_soc_codec *rk1000_codec_codec;
+#define HP_OUT 0
+#define HP_IN  1
+#define USE_MIC_IN
+#define USE_LPF
+
+#define FREQ441KHZ    (0x11 << 1)
+/* rk1000 output volume,DAC Digital Gain */
+/* 0x0000 ~ 0xF42 */
+#define VOLUME_OUTPUT 0xF42
+/* 0x0 ~ 0x3f(bit0-bit5)        max=0x0(+6DB) min=0x3f(-60DB)   Analog Gain */
+#define VOLUME_CODEC_PA 0x0
+
+/* rk1000 input volume,rk610 can not adjust the recording volume */
+#define VOLUME_INPUT 0x07
+
+#define OUT_CAPLESS  (1)
+
+/* 1:set pll from rk1000 */
+#define RK1000_CTL_PLL 0
 
-//static u32 gVolReg = 0x0f;  ///0x0f; //ÓÃÓڼǼÒôÁ¿¼Ä´æÆ÷
-//static u32 gCodecVol = 0x0f;
-static u8 gR0AReg = 0;  //ÓÃÓڼǼR0A¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0AÍ£Ö¹clk
-static u8 gR0BReg = 0;  //ÓÃÓڼǼR0B¼Ä´æÆ÷µÄÖµ£¬ÓÃÓڸıä²ÉÑùÂÊǰͨ¹ýR0BÍ£Ö¹interplateºÍdecimation
-static u8 gR1314Reg = 0;  //ÓÃÓڼǼR13,R14¼Ä´æÆ÷µÄÖµ£¬ÓÃÓÚFMÒôÁ¿Îª0ʱ
+static u8 g_r0_a_reg;
+static u8 g_r0_b_reg;
 
 /*
  * rk1000 register cache
@@ -78,48 +82,86 @@ static const u16 rk1000_codec_reg[] = {
        0x0000, 0x00ff, 0x00ff, 0x00ff,  /* 0x1a */
 };
 
+static struct snd_soc_codec *rk1000_codec_codec;
 /* codec private data */
 struct rk1000_codec_priv {
        enum snd_soc_control_type control_type;
-       void *control_data;
-       
        unsigned int sysclk;
        struct snd_soc_codec codec;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
        u16 reg_cache[RK1000_CODEC_NUM_REG];
+
+       struct delayed_work rk1000_delayed_work;
+       unsigned int spk_ctrl_io;
+       enum of_gpio_flags flags;
+       /*
+               Some amplifiers enable a longer time.
+               config after pa_enable_io delay pa_enable_time(ms)
+               so value range is 0 - 8000.
+       */
+       unsigned int pa_enable_time;
+       /* if found boot pop,set boot_depop 1 test */
+       int boot_depop;
+       int call_enable;
+       int headset_status;
 };
 
+
+static void spk_ctrl_fun(int status)
+{
+       struct rk1000_codec_priv *rk1000_codec;
+
+       if (rk1000_codec_codec == NULL)
+               return;
+       rk1000_codec = snd_soc_codec_get_drvdata(rk1000_codec_codec);
+       if (rk1000_codec == NULL)
+               return;
+       if (!rk1000_codec->spk_ctrl_io)
+               return;
+       DBG("%s:: spk status = %d\n", __func__, status);
+       if (status)
+               gpio_set_value(rk1000_codec->spk_ctrl_io,
+                              rk1000_codec->flags);
+       else
+               gpio_set_value(rk1000_codec->spk_ctrl_io,
+                              !rk1000_codec->flags);
+}
+
+
 /*
  * read rk1000 register cache
  */
-static inline unsigned int rk1000_codec_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
+static unsigned int rk1000_codec_read_reg_cache(struct snd_soc_codec *codec,
+                                               unsigned int reg)
 {
        u16 *cache = codec->reg_cache;
+
        if (reg > RK1000_CACHE_REGNUM)
                return -1;
        return cache[reg];
 }
 
-static unsigned int rk1000_codec_read(struct snd_soc_codec *codec, unsigned int r)
-{      
+static unsigned int rk1000_codec_read(struct snd_soc_codec *codec,
+                                     unsigned int r)
+{
        struct i2c_msg xfer[1];
-       u8 reg = r;
+       int reg;
        int ret;
-       struct i2c_client *client = codec->control_data;
+       struct i2c_client *i2c;
 
+       reg = r;
+       i2c = to_i2c_client(codec->dev);
        /* Read register */
-       xfer[0].addr = (client->addr& 0x60)|(reg);
+       xfer[0].addr = (i2c->addr & 0x60) | (reg);
        xfer[0].flags = I2C_M_RD;
        xfer[0].len = 1;
-       xfer[0].buf = &reg;
-       xfer[0].scl_rate = 100*1000;
-       ret = i2c_transfer(client->adapter, xfer, 1);
+       xfer[0].buf = (unsigned char *)&reg;
+       xfer[0].scl_rate = 100000;
+       ret = i2c_transfer(i2c->adapter, xfer, 1);
        if (ret != 1) {
-               dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
+               dev_err(&i2c->dev, "i2c_transfer() returned %d\n", ret);
                return 0;
        }
-
        return reg;
 }
 
@@ -127,143 +169,109 @@ static unsigned int rk1000_codec_read(struct snd_soc_codec *codec, unsigned int
  * write rk1000 register cache
  */
 static inline void rk1000_codec_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
+                                               unsigned int reg,
+                                               unsigned int value)
 {
-       u16 *cache = codec->reg_cache;
+       u16 *cache;
+
+       cache = codec->reg_cache;
        if (reg > RK1000_CACHE_REGNUM)
                return;
        cache[reg] = value;
 }
 
 static int rk1000_codec_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
+                             unsigned int value)
 {
+#ifdef CONFIG_MODEM_SOUND
+       struct rk1000_codec_priv *rk1000_codec;
+#endif
        u8 data[2];
        struct i2c_client *i2c;
-       DBG("Enter-%s::reg=0x%02X, value=0x%02X\n",__FUNCTION__, reg, value);
+
+       i2c = to_i2c_client(codec->dev);
+#ifdef CONFIG_MODEM_SOUND
+       rk1000_codec = snd_soc_codec_get_drvdata(rk1000_codec_codec);
+       if (rk1000_codec->call_enable)
+               return 0;
+#endif
+       DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n", __func__,
+           __LINE__, reg, value);
        data[0] = value & 0x00ff;
-       rk1000_codec_write_reg_cache (codec, reg, value);
-       i2c = (struct i2c_client *)codec->control_data;
        i2c->addr = (i2c->addr & 0x60)|reg;
-       if (codec->hw_write(codec->control_data, data, 1) == 1){
-//                DBG("================%s Run OK====%d============\n",__FUNCTION__,__LINE__);
+       if (codec->hw_write(i2c, data, 1) == 1) {
+               DBG("====%s %d Run OK=======\n", __func__, __LINE__);
+               rk1000_codec_write_reg_cache(codec, reg, value);
                return 0;
-       }else{
-               DBG("================%s Run EIO=======%d=========\n",__FUNCTION__,__LINE__);
+       } else {
+               DBG("====%s %d Run EIO=====\n", __func__, __LINE__);
                return -EIO;
-        }
+       }
 }
 
-static const struct snd_kcontrol_new rk1000_codec_snd_controls[] = {
-
-SOC_DOUBLE_R("Capture Volume", ACCELCODEC_R0C, ACCELCODEC_R0D, 0, 15, 0),
-SOC_DOUBLE_R("Capture Switch", ACCELCODEC_R0C, ACCELCODEC_R0D, 7, 1, 1),
-
-SOC_DOUBLE_R("PCM Volume", ACCELCODEC_R0D, ACCELCODEC_R0E, 0, 7, 0),
-
-//SOC_SINGLE("Left ADC Capture Volume", ACCELCODEC_R17, 0, 63, 0),
-//SOC_SINGLE("Right ADC Capture Volume", ACCELCODEC_R18, 0, 63, 0),
-
-
-};
-
-
-/* Left Mixer */
-static const struct snd_kcontrol_new rk1000_codec_left_mixer_controls[] = {
-SOC_DAPM_SINGLE("Playback Switch", ACCELCODEC_R15, 6, 1, 0),
-SOC_DAPM_SINGLE("Left Bypass Switch", ACCELCODEC_R15, 2, 1, 0),
+#ifdef CONFIG_MODEM_SOUND
+static int rk1000_codec_write_incall(struct snd_soc_codec *codec,
+                                    unsigned int reg, unsigned int value)
+{
+       u8 data[2];
+       struct i2c_client *i2c;
 
-};
+       DBG("Enter::%s, %d, reg=0x%02X, value=0x%02X\n",
+           __func__, __LINE__, reg, value);
+       i2c = to_i2c_client(codec->dev);
+       data[0] = value & 0x00ff;
+       rk1000_codec_write_reg_cache(codec, reg, value);
+       i2c = (struct i2c_client *)codec->control_data;
+       i2c->addr = (i2c->addr & 0x60) | reg;
+       if (codec->hw_write(i2c, data, 1) == 1)
+               return 0;
+       else
+               return -EIO;
+}
 
-/* Right Mixer */
-static const struct snd_kcontrol_new rk1000_codec_right_mixer_controls[] = {
-SOC_DAPM_SINGLE("Playback Switch", ACCELCODEC_R15, 7, 1, 0),
-SOC_DAPM_SINGLE("Left Bypass Switch", ACCELCODEC_R15, 3, 1, 0),
+void call_set_spk(int on)
+{
+       struct rk1000_codec_priv *rk1000_codec;
 
-};
+       if (!rk1000_codec_codec)
+               return;
+       rk1000_codec = snd_soc_codec_get_drvdata(rk1000codec_codec);
+       if (!rk1000_codec)
+               return;
 
+       switch (on) {
+       case 0:
+               /* modem exit call,codec disable loopback */
+               DBG("%s modem exit call\n", __func__);
+               rk1000_codec_write_incall(rk1000_codec_codec,
+                                         ACCELCODEC_R0E, 0x80);
+               rk1000_codec->call_enable = 0;
+               break;
+       case 1:
+               /* modem calling,codec enable loopback,
+               * spk hp different volume */
+               DBG("%s spk incalling\n", __func__);
+               rk1000_codec->call_enable = 1;
+               rk1000_codec_write_incall(rk1000_codec_codec,
+                                         ACCELCODEC_R0E, 0x00);
+               return;
+       case 2:
+               DBG("%s hp incalling\n", __func__);
+               rk1000_codec->call_enable = 1;
+               rk1000_codec_write_incall(rk1000_codec_codec,
+                                         ACCELCODEC_R0E, 0x00);
+               break;
+       case 3:
+               DBG("%s bt incalling\n", __func__);
+               rk1000_codec->call_enable = 1;
+               rk1000_codec_write_incall(rk1000_codec_codec,
+                                         ACCELCODEC_R0E, 0x00);
+               break;
+       }
+}
+#endif
 
-static const struct snd_soc_dapm_widget rk1000_codec_dapm_widgets[] = {
-       SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
-               &rk1000_codec_left_mixer_controls[0],
-               ARRAY_SIZE(rk1000_codec_left_mixer_controls)),
-       SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
-               &rk1000_codec_right_mixer_controls[0],
-               ARRAY_SIZE(rk1000_codec_right_mixer_controls)),
-    
-       //SND_SOC_DAPM_PGA("Right Out 1", ACCELCODEC_R1E, 0, 0, NULL, 0),
-       //SND_SOC_DAPM_PGA("Left Out 1", ACCELCODEC_R1E, 1, 0, NULL, 0),
-       //SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ACCELCODEC_R1F, 1, 0),
-       //SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ACCELCODEC_R1F, 2, 0),
-    
-       SND_SOC_DAPM_ADC("ADC", "Capture", ACCELCODEC_R1D, 6, 1),
-       SND_SOC_DAPM_ADC("ADC BUFF", "Capture BUFF", ACCELCODEC_R1D, 2, 0),
-    
-     
-       SND_SOC_DAPM_OUTPUT("LOUT1"),
-       SND_SOC_DAPM_OUTPUT("ROUT1"),
-    
-       SND_SOC_DAPM_INPUT("LINPUT1"),
-       SND_SOC_DAPM_INPUT("RINPUT1"),
-};
 
-static const struct snd_soc_dapm_route audio_map[] = {
-       /* left mixer */
-       {"Left Mixer", "Playback Switch", "Left DAC"},
-       {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
-       {"Right Mixer", "Playback Switch", "Right DAC"},
-       {"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
-    
-       /* left out 1 */
-       {"Left Out 1", NULL, "Left Mixer"},
-       {"LOUT1", NULL, "Left Out 1"},
-    
-    
-       /* right out 1 */
-       {"Right Out 1", NULL, "Right Mixer"},
-       {"ROUT1", NULL, "Right Out 1"},
-    
-       /* Left Line Mux */
-       {"Left Line Mux", "Line 1", "LINPUT1"},
-       {"Left Line Mux", "PGA", "Left PGA Mux"},
-       {"Left Line Mux", "Differential", "Differential Mux"},
-    
-       /* Right Line Mux */
-       {"Right Line Mux", "Line 1", "RINPUT1"},
-       {"Right Line Mux", "PGA", "Right PGA Mux"},
-       {"Right Line Mux", "Differential", "Differential Mux"},
-    
-       /* Left PGA Mux */
-       {"Left PGA Mux", "Line 1", "LINPUT1"},
-       {"Left PGA Mux", "Line 2", "LINPUT2"},
-       {"Left PGA Mux", "Line 3", "LINPUT3"},
-       {"Left PGA Mux", "Differential", "Differential Mux"},
-    
-       /* Right PGA Mux */
-       {"Right PGA Mux", "Line 1", "RINPUT1"},
-       {"Right PGA Mux", "Differential", "Differential Mux"},
-    
-       /* Differential Mux */
-       {"Differential Mux", "Line 1", "LINPUT1"},
-       {"Differential Mux", "Line 1", "RINPUT1"},
-    
-       /* Left ADC Mux */
-       {"Left ADC Mux", "Stereo", "Left PGA Mux"},
-       {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
-       {"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
-    
-       /* Right ADC Mux */
-       {"Right ADC Mux", "Stereo", "Right PGA Mux"},
-       {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
-       {"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
-    
-       /* ADC */
-       {"Left ADC", NULL, "Left ADC Mux"},
-       {"Right ADC", NULL, "Right ADC Mux"},
-    
-       /* terminator */
-       {NULL, NULL, NULL},
-};
 
 struct _coeff_div {
        u32 mclk;
@@ -277,62 +285,52 @@ struct _coeff_div {
 /* codec hifi mclk clock divider coefficients */
 static const struct _coeff_div coeff_div[] = {
        /* 8k */
-       {12288000, 8000, 1536, 0x6, 0x0,ASC_BCLKDIV_16},
-       {11289600, 8000, 1408, 0x16, 0x0,ASC_BCLKDIV_16},
-       {18432000, 8000, 2304, 0x7, 0x0,ASC_BCLKDIV_16},
-       {16934400, 8000, 2112, 0x17, 0x0,ASC_BCLKDIV_16},
-       {8192000, 8000, 1024, 0x0, 0x0,ASC_BCLKDIV_16},
-       {12000000, 8000, 1500, 0x6, 0x1,ASC_BCLKDIV_16},
-    
+       {12288000, 8000, 1536, 0x6, 0x0, ASC_BCLKDIV_16},
+       {11289600, 8000, 1408, 0x16, 0x0, ASC_BCLKDIV_16},
+       {18432000, 8000, 2304, 0x7, 0x0, ASC_BCLKDIV_16},
+       {16934400, 8000, 2112, 0x17, 0x0, ASC_BCLKDIV_16},
+       {8192000, 8000, 1024, 0x0, 0x0, ASC_BCLKDIV_16},
+       {12000000, 8000, 1500, 0x6, 0x1, ASC_BCLKDIV_16},
        /* 11.025k */
-       {11289600, 11025, 1024, 0x18, 0x0,ASC_BCLKDIV_16},
-       {16934400, 11025, 1536, 0x19, 0x0,ASC_BCLKDIV_16},
-       {12000000, 11025, 1088, 0x19, 0x1,ASC_BCLKDIV_16},
-    
-    /* 12k */
-       {12288000, 12000, 1024, 0x8, 0x0,ASC_BCLKDIV_16},
-       {18432000, 12000, 1536, 0x9, 0x0,ASC_BCLKDIV_16},
-       {12000000, 12000, 1000, 0x8, 0x1,ASC_BCLKDIV_16},
-    
+       {11289600, 11025, 1024, 0x18, 0x0, ASC_BCLKDIV_16},
+       {16934400, 11025, 1536, 0x19, 0x0, ASC_BCLKDIV_16},
+       {12000000, 11025, 1088, 0x19, 0x1, ASC_BCLKDIV_16},
+       /* 12k */
+       {12288000, 12000, 1024, 0x8, 0x0, ASC_BCLKDIV_16},
+       {18432000, 12000, 1536, 0x9, 0x0, ASC_BCLKDIV_16},
+       {12000000, 12000, 1000, 0x8, 0x1, ASC_BCLKDIV_16},
        /* 16k */
-       {12288000, 16000, 768, 0xa, 0x0,ASC_BCLKDIV_8},
-       {18432000, 16000, 1152, 0xb, 0x0,ASC_BCLKDIV_8},
-       {12000000, 16000, 750, 0xa, 0x1,ASC_BCLKDIV_8},
-    
+       {12288000, 16000, 768, 0xa, 0x0, ASC_BCLKDIV_8},
+       {18432000, 16000, 1152, 0xb, 0x0, ASC_BCLKDIV_8},
+       {12000000, 16000, 750, 0xa, 0x1, ASC_BCLKDIV_8},
        /* 22.05k */
-       {11289600, 22050, 512, 0x1a, 0x0,ASC_BCLKDIV_8},
-       {16934400, 22050, 768, 0x1b, 0x0,ASC_BCLKDIV_8},
-       {12000000, 22050, 544, 0x1b, 0x1,ASC_BCLKDIV_8},
-    
-    /* 24k */
-       {12288000, 24000, 512, 0x1c, 0x0,ASC_BCLKDIV_8},
-       {18432000, 24000, 768, 0x1d, 0x0,ASC_BCLKDIV_8},
-       {12000000, 24000, 500, 0x1c, 0x1,ASC_BCLKDIV_8},
-       
+       {11289600, 22050, 512, 0x1a, 0x0, ASC_BCLKDIV_8},
+       {16934400, 22050, 768, 0x1b, 0x0, ASC_BCLKDIV_8},
+       {12000000, 22050, 544, 0x1b, 0x1, ASC_BCLKDIV_8},
+       /* 24k */
+       {12288000, 24000, 512, 0x1c, 0x0, ASC_BCLKDIV_8},
+       {18432000, 24000, 768, 0x1d, 0x0, ASC_BCLKDIV_8},
+       {12000000, 24000, 500, 0x1c, 0x1, ASC_BCLKDIV_8},
        /* 32k */
-       {12288000, 32000, 384, 0xc, 0x0,ASC_BCLKDIV_8},
-       {18432000, 32000, 576, 0xd, 0x0,ASC_BCLKDIV_8},
-       {12000000, 32000, 375, 0xa, 0x1,ASC_BCLKDIV_8},
-    
+       {12288000, 32000, 384, 0xc, 0x0, ASC_BCLKDIV_8},
+       {18432000, 32000, 576, 0xd, 0x0, ASC_BCLKDIV_8},
+       {12000000, 32000, 375, 0xa, 0x1, ASC_BCLKDIV_8},
        /* 44.1k */
-       {11289600, 44100, 256, 0x10, 0x0,ASC_BCLKDIV_8},
-       {16934400, 44100, 384, 0x11, 0x0,ASC_BCLKDIV_8},
-       {12000000, 44100, 272, 0x11, 0x1,ASC_BCLKDIV_8},
-    
+       {11289600, 44100, 256, 0x10, 0x0, ASC_BCLKDIV_4},
+       {16934400, 44100, 384, 0x11, 0x0, ASC_BCLKDIV_8},
+       {12000000, 44100, 272, 0x11, 0x1, ASC_BCLKDIV_8},
        /* 48k */
-       {12288000, 48000, 256, 0x0, 0x0,ASC_BCLKDIV_4},
-       {18432000, 48000, 384, 0x1, 0x0,ASC_BCLKDIV_4},
-       {12000000, 48000, 250, 0x0, 0x1,ASC_BCLKDIV_4},
-    
+       {12288000, 48000, 256, 0x0, 0x0, ASC_BCLKDIV_4},
+       {18432000, 48000, 384, 0x1, 0x0, ASC_BCLKDIV_4},
+       {12000000, 48000, 250, 0x0, 0x1, ASC_BCLKDIV_4},
        /* 88.2k */
-       {11289600, 88200, 128, 0x1e, 0x0,ASC_BCLKDIV_4},
-       {16934400, 88200, 192, 0x1f, 0x0,ASC_BCLKDIV_4},
-       {12000000, 88200, 136, 0x1f, 0x1,ASC_BCLKDIV_4},
-    
+       {11289600, 88200, 128, 0x1e, 0x0, ASC_BCLKDIV_4},
+       {16934400, 88200, 192, 0x1f, 0x0, ASC_BCLKDIV_4},
+       {12000000, 88200, 136, 0x1f, 0x1, ASC_BCLKDIV_4},
        /* 96k */
-       {12288000, 96000, 128, 0xe, 0x0,ASC_BCLKDIV_4},
-       {18432000, 96000, 192, 0xf, 0x0,ASC_BCLKDIV_4},
-       {12000000, 96000, 125, 0xe, 0x1,ASC_BCLKDIV_4},
+       {12288000, 96000, 128, 0xe, 0x0, ASC_BCLKDIV_4},
+       {18432000, 96000, 192, 0xf, 0x0, ASC_BCLKDIV_4},
+       {12000000, 96000, 125, 0xe, 0x1, ASC_BCLKDIV_4},
 };
 
 static inline int get_coeff(int mclk, int rate)
@@ -343,7 +341,6 @@ static inline int get_coeff(int mclk, int rate)
                if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
                        return i;
        }
-
        return -EINVAL;
 }
 
@@ -377,17 +374,50 @@ static struct snd_pcm_hw_constraint_list constraints_12 = {
        .list   = rates_12,
 };
 
+static int rk1000_codec_set_bias_level(struct snd_soc_codec *codec,
+                                      enum snd_soc_bias_level level)
+{
+       DBG("Enter::%s----%d now_level =%d  old_level = %d\n",
+           __func__, __LINE__, level, codec->dapm.bias_level);
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               rk1000_codec_write(codec, ACCELCODEC_R1D, 0x2a);
+               rk1000_codec_write(codec, ACCELCODEC_R1E, 0x40);
+               rk1000_codec_write(codec, ACCELCODEC_R1F, 0x49);
+               /*VREF, VMID=2x50k, digital enabled */
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               DBG("rk1000 standby\n");
+               rk1000_codec_write(codec, ACCELCODEC_R1D, 0xFF);
+               rk1000_codec_write(codec, ACCELCODEC_R1E, 0xFF);
+               rk1000_codec_write(codec, ACCELCODEC_R1F, 0xFF);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               DBG("rk1000 power off\n");
+               spk_ctrl_fun(GPIO_LOW);
+               rk1000_codec_write(codec, ACCELCODEC_R1D, 0xFF);
+               rk1000_codec_write(codec, ACCELCODEC_R1E, 0xFF);
+               rk1000_codec_write(codec, ACCELCODEC_R1F, 0xFF);
+               break;
+       }
+       codec->dapm.bias_level = level;
+       return 0;
+}
 /*
  * Note that this should be called from init rather than from hw_params.
  */
 static int rk1000_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-               int clk_id, unsigned int freq, int dir)
+                                      int clk_id, unsigned int freq, int dir)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       struct rk1000_codec_priv *rk1000_codec = snd_soc_codec_get_drvdata(codec);
-       
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-       freq = 12000000;        
+       struct rk1000_codec_priv *rk1000_codec;
+
+       DBG("Enter::%s----%d\n", __func__, __LINE__);
+       rk1000_codec = snd_soc_codec_get_drvdata(codec);
        switch (freq) {
        case 11289600:
        case 18432000:
@@ -415,23 +445,27 @@ static int rk1000_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 }
 
 static int rk1000_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
-               unsigned int fmt)
+                                   unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct rk1000_codec_priv *rk1000_codec;
        u16 iface = 0;
 
+       rk1000_codec = snd_soc_codec_get_drvdata(codec);
+       /* setup Vmid and Vref, other module power down */
+       rk1000_codec_write(codec, ACCELCODEC_R1D, 0x2a);
+       rk1000_codec_write(codec, ACCELCODEC_R1E, 0x40);
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                iface = 0x0040;
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
-               iface = 0x0020;
+               iface = 0x0000;
                break;
        default:
                return -EINVAL;
        }
-
        /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
@@ -451,7 +485,6 @@ static int rk1000_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
        default:
                return -EINVAL;
        }
-
        /* clock inversion */
        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
@@ -468,216 +501,122 @@ static int rk1000_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
        default:
                return -EINVAL;
        }
-
-       DBG("Enter::%s----%d  iface=%x\n",__FUNCTION__,__LINE__,iface);
+       DBG("Enter::%s----%d  iface=%x\n", __func__, __LINE__, iface);
        rk1000_codec_write(codec, ACCELCODEC_R09, iface);
        return 0;
 }
 
-static int rk1000_codec_pcm_startup(struct snd_pcm_substream *substream,
-                             struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->codec;
-       struct rk1000_codec_priv *rk1000_codec = snd_soc_codec_get_drvdata(codec);
-       
-       /* The set of sample rates that can be supported depends on the
-        * MCLK supplied to the CODEC - enforce this.
-        */
-       DBG("Enter::%s----%d  rk1000_codec->sysclk=%d\n",__FUNCTION__,__LINE__,rk1000_codec->sysclk); 
-//     if (!rk1000_codec->sysclk) {
-//             dev_err(codec->dev,
-//                     "No MCLK configured, call set_sysclk() on init\n");
-//             return -EINVAL;
-//     }
-
-#if 0
-    snd_pcm_hw_constraint_list(substream->runtime, 0,
-                                  SNDRV_PCM_HW_PARAM_RATE,
-                                  rk1000_codec->sysclk_constraints);
-#endif
-       return 0;
-}
+
 
 static int rk1000_codec_pcm_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params,
-                               struct snd_soc_dai *dai)
+                                     struct snd_pcm_hw_params *params,
+                                     struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->codec;
-       struct rk1000_codec_priv *rk1000_codec = snd_soc_codec_get_drvdata(codec);
-       
-       u16 iface = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3;
-       u16 srate = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R00) & 0x180;
+       u16 iface;
        int coeff;
-
-       rk1000_codec->sysclk = 12000000;
-       /*by Vincent Hsiung for EQ Vol Change*/
-       #define HW_PARAMS_FLAG_EQVOL_ON 0x21
-       #define HW_PARAMS_FLAG_EQVOL_OFF 0x22
-       if (params->flags == HW_PARAMS_FLAG_EQVOL_ON)
-       {
-               u16 r17 = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R17);
-               u16 r18 = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R18);
-               
-               r17 &= (~0x3f); //6db
-               r18 &= (~0x3f); //6db
-               
-               rk1000_codec_write(codec, ACCELCODEC_R17, r17);
-               rk1000_codec_write(codec, ACCELCODEC_R18, r18);
-               
-               return 0;
-       }
-       else if (params->flags == HW_PARAMS_FLAG_EQVOL_OFF)
-       {
-               u16 r17 = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R17);
-               u16 r18 = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R18);
-               
-               r17 &= (~0x3f); 
-               r17 |= 0x0f; //0db
-               
-               r18 &= (~0x3f); 
-               r18 |= 0x0f; //0db
-               
-               rk1000_codec_write(codec, ACCELCODEC_R17, r17);
-               rk1000_codec_write(codec, ACCELCODEC_R18, r18);
-               return 0;
-       } 
-       
-       coeff = get_coeff(rk1000_codec->sysclk, params_rate(params));
-
-       /* bit size */
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
-               iface |= 0x0004;
-               break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               iface |= 0x0008;
-               break;
-       case SNDRV_PCM_FORMAT_S32_LE:
-               iface |= 0x000c;
-               break;
-       }
-       DBG("Enter::%s----%d  iface=%x srate =%x rate=%d\n",__FUNCTION__,__LINE__,iface,srate,params_rate(params));
-       
-       rk1000_codec_write(codec,ACCELCODEC_R0C, 0x17);  
-       rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);   //soft mute
-       //±ØÐëÏȽ«clkºÍEN_INT¶¼disableµô£¬·ñÔòÇл»bclk·ÖƵֵ¿ÉÄܵ¼ÖÂcodecÄÚ²¿Ê±Ðò»ìÂÒµô£¬
-       //±íÏÖ³öÀ´µÄÏÖÏóÊÇ£¬ÒÔºóµÄÒôÀÖ¶¼±ä³ÉÁËÔëÒô£¬¶øÇÒ¾ÍËã°ÑÊäÈëcodecµÄI2S_DATAOUT¶Ï¿ªÒ²Ò»Ñù³öÔëÒô
-       rk1000_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE);  //0x00
-       
+       struct snd_soc_pcm_runtime *rtd;
+       struct snd_soc_codec *codec;
+       unsigned int dai_fmt;
+
+       rtd = substream->private_data;
+       codec = rtd->codec;
+       dai_fmt = rtd->card->dai_link[0].dai_fmt;
+       iface = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R09) & 0x1f3;
+       coeff = 0;
+       rk1000_codec_write(codec, ACCELCODEC_R0C, 0x17);
+       rk1000_codec_write(codec, ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|
+                          ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);
+       rk1000_codec_write(codec, ACCELCODEC_R0B,
+                          ASC_DEC_DISABLE|ASC_INT_DISABLE);
        /* set iface & srate */
+       if ((dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM)
+               iface |= ASC_INVERT_BCLK;
        rk1000_codec_write(codec, ACCELCODEC_R09, iface);
        if (coeff >= 0)
-       {
-       //      rk1000_codec_write(codec, ACCELCODEC_R0A, (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb|ASC_CLKNODIV|ASC_CLK_ENABLE);
                rk1000_codec_write(codec, ACCELCODEC_R0A, 0xa0);
-       //      rk1000_codec_write(codec, ACCELCODEC_R00, srate|coeff_div[coeff].bclk);
-       }               
-       rk1000_codec_write(codec,ACCELCODEC_R0B, gR0BReg);
-       
+       rk1000_codec_write(codec, ACCELCODEC_R0B, g_r0_b_reg);
        return 0;
 }
 
-void PhaseOut(struct snd_soc_codec *codec,u32 nStep, u32 us)
-{
-        DBG("%s[%d]\n",__FUNCTION__,__LINE__); 
-        rk1000_codec_write(codec,ACCELCODEC_R17, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOL
-        rk1000_codec_write(codec,ACCELCODEC_R18, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOR
-        udelay(us);
-}
 
-void PhaseIn(struct snd_soc_codec *codec,u32 nStep, u32 us)
-{
-        DBG("%s[%d]\n",__FUNCTION__,__LINE__); 
-        rk1000_codec_write(codec,ACCELCODEC_R17, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOL gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOL
-        rk1000_codec_write(codec,ACCELCODEC_R18, 0x00|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN); //gVolReg|ASC_OUTPUT_ACTIVE|ASC_CROSSZERO_EN);  //AOR
-        udelay(us);
-}
 
 static int rk1000_codec_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
+       struct rk1000_codec_priv *rk1000_codec;
 
-       DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
-    
-       if (mute)
-       {
-               PhaseOut(codec,1, 5000);
-               rk1000_codec_write(codec,ACCELCODEC_R19, 0xFF);  //AOM
-               rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);  //soft mute   
-       }
-       else
-       {               
-               rk1000_codec_write(codec,ACCELCODEC_R1D, 0x2a);  //setup Vmid and Vref, other module power down
-               rk1000_codec_write(codec,ACCELCODEC_R1E, 0x40);  ///|ASC_PDASDML_ENABLE);
-               rk1000_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);  ///|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE);
-               PhaseIn(codec,1, 5000);
-       //      if(gCodecVol != 0)
-               {
-                       rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_ACTIVE_L|ASC_INT_ACTIVE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);
-        }
-               rk1000_codec_write(codec,ACCELCODEC_R19, 0x7F);  //AOM
-               #if 0
-               /*disable speaker */
-               rockchip_mux_api_set(SPK_IOMUX_PIN_NAME, SPK_IOMUX_PIN_DIR);
-               GPIOSetPinDirection(SPK_CTRL_PIN,GPIO_OUT);
-               GPIOSetPinLevel(SPK_CTRL_PIN,GPIO_HIGH);
+       DBG("Enter::%s----%d--mute=%d\n", __func__, __LINE__, mute);
+       rk1000_codec = snd_soc_codec_get_drvdata(codec);
+       if (mute) {
+               /* AOL */
+               rk1000_codec_write(codec, ACCELCODEC_R17, 0xFF);
+               /* AOR */
+               rk1000_codec_write(codec, ACCELCODEC_R18, 0xFF);
+               /* AOM */
+               rk1000_codec_write(codec, ACCELCODEC_R19, 0xFF);
+               /* soft mute */
+               rk1000_codec_write(codec, ACCELCODEC_R04, ASC_INT_MUTE_L|
+                                  ASC_INT_MUTE_R | ASC_SIDETONE_L_OFF |
+                                  ASC_SIDETONE_R_OFF);
+       } else {
+               /* setup Vmid and Vref, other module power down */
+               rk1000_codec_write(codec, ACCELCODEC_R1D, 0x2a);
+               rk1000_codec_write(codec, ACCELCODEC_R1E, 0x40);
+               /* AOL */
+               rk1000_codec_write(codec, ACCELCODEC_R17, VOLUME_CODEC_PA |
+                                  ASC_OUTPUT_ACTIVE | ASC_CROSSZERO_EN);
+               /* AOR */
+               rk1000_codec_write(codec, ACCELCODEC_R18, VOLUME_CODEC_PA |
+                                  ASC_OUTPUT_ACTIVE | ASC_CROSSZERO_EN);
+               rk1000_codec_write(codec, ACCELCODEC_R04, ASC_INT_ACTIVE_L|
+                                  ASC_INT_ACTIVE_R | ASC_SIDETONE_L_OFF|
+                                  ASC_SIDETONE_R_OFF);
+               /* AOM */
+               rk1000_codec_write(codec, ACCELCODEC_R19, 0x7F);
+               #if OUT_CAPLESS
+               rk1000_codec_write(codec, ACCELCODEC_R1F, 0x09|
+                                  ASC_PDMIXM_ENABLE);
+               #else
+               rk1000_codec_write(codec, ACCELCODEC_R1F, 0x09|
+                                  ASC_PDMIXM_ENABLE | ASC_PDPAM_ENABLE);
                #endif
        }
        return 0;
 }
 
-static int rk1000_codec_set_bias_level(struct snd_soc_codec *codec,
-                                enum snd_soc_bias_level level)
+static void rk1000_delayedwork_fun(struct work_struct *work)
 {
-       u16 pwr_reg = rk1000_codec_read_reg_cache(codec, ACCELCODEC_R1D) & ~0x1c1;
-       DBG("Enter::%s----%d level =%d\n",__FUNCTION__,__LINE__,level);
-       switch (level) {
-       case SND_SOC_BIAS_ON:
-               break;
-
-       case SND_SOC_BIAS_PREPARE:
-               /* VREF, VMID=2x50k, digital enabled */
-               rk1000_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080);
-               break;
-
-       case SND_SOC_BIAS_STANDBY:
-               if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-                       /* VREF, VMID=2x5k */
-                       rk1000_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080);
-
-                       /* Charge caps */
-                       msleep(100);
-               }
-
-               /* VREF, VMID=2*500k, digital stopped */
-               rk1000_codec_write(codec, ACCELCODEC_R1D, pwr_reg | 0x0080);
-               break;
+       struct snd_soc_codec *codec;
+       struct rk1000_codec_priv *rk1000_codec;
 
-       case SND_SOC_BIAS_OFF:
-               rk1000_codec_write(codec, ACCELCODEC_R1D, 0x0000);
-               break;
+       DBG("--------%s----------\n", __func__);
+       codec = rk1000_codec_codec;
+       rk1000_codec = snd_soc_codec_get_drvdata(codec);
+       if (!rk1000_codec->boot_depop) {
+               #if OUT_CAPLESS
+               rk1000_codec_write(codec, ACCELCODEC_R1F,
+                                  0x09 | ASC_PDMIXM_ENABLE);
+               #else
+               rk1000_codec_write(codec, ACCELCODEC_R1F,
+                                  0x09 | ASC_PDMIXM_ENABLE | ASC_PDPAM_ENABLE);
+               #endif
        }
-       codec->dapm.bias_level = level;
-       return 0;
+       spk_ctrl_fun(GPIO_HIGH);
 }
 
-#define RK1000_CODEC_RATES SNDRV_PCM_RATE_8000_96000
 
-#define RK1000_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
-       SNDRV_PCM_FMTBIT_S24_LE)
 
 static struct snd_soc_dai_ops rk1000_codec_ops = {
-       .startup = rk1000_codec_pcm_startup,
        .hw_params = rk1000_codec_pcm_hw_params,
        .set_fmt = rk1000_codec_set_dai_fmt,
        .set_sysclk = rk1000_codec_set_dai_sysclk,
        .digital_mute = rk1000_codec_mute,
 };
 
+#define RK1000_CODEC_RATES SNDRV_PCM_RATE_8000_96000
+#define RK1000_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+                               SNDRV_PCM_FMTBIT_S20_3LE |\
+                               SNDRV_PCM_FMTBIT_S24_LE)
 static struct snd_soc_dai_driver rk1000_codec_dai[] = {
        {
                .name = "rk1000_codec",
@@ -700,212 +639,222 @@ static struct snd_soc_dai_driver rk1000_codec_dai[] = {
        }
 };
 
-static int rk1000_codec_suspend(struct snd_soc_codec *codec)
-{
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-       rk1000_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
 
-static int rk1000_codec_resume(struct snd_soc_codec *codec)
+void rk1000_codec_reg_set(void)
 {
-       int i;
-       u8 data[2];
-       struct i2c_client *i2c;
-       u16 *cache = codec->reg_cache;
-       
-       DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
-       /* Sync reg_cache with the hardware */
-       for (i = 0; i < RK1000_CODEC_NUM_REG; i++) {
-               data[0] = cache[i] & 0x00ff;
-               i2c = (struct i2c_client *)codec->control_data;
-               i2c->addr = (i2c->addr & 0x60)|i;
-               codec->hw_write(codec->control_data, data, 1);
+       struct snd_soc_codec *codec;
+       struct rk1000_codec_priv *rk1000_codec;
+       unsigned int digital_gain;
+       unsigned int mic_vol;
+
+       mic_vol = VOLUME_INPUT;
+       codec = rk1000_codec_codec;
+       rk1000_codec = snd_soc_codec_get_drvdata(codec);
+       rk1000_codec_write(codec, ACCELCODEC_R1D, 0x30);
+       rk1000_codec_write(codec, ACCELCODEC_R1E, 0x40);
+#ifdef USE_LPF
+       /*Route R-LPF->R-Mixer, L-LPF->L-Mixer*/
+       rk1000_codec_write(codec, ACCELCODEC_R15, 0xC1);
+#else
+       /*Route RDAC->R-Mixer, LDAC->L->Mixer*/
+       rk1000_codec_write(codec, ACCELCODEC_R15, 0x0C);
+#endif
+       /*With Cap Output, VMID ramp up slow*/
+       rk1000_codec_write(codec, ACCELCODEC_R1A, 0x14);
+       mdelay(10);
+       rk1000_codec_write(codec, ACCELCODEC_R0C, 0x10 | ASC_INPUT_VOL_0DB);
+       rk1000_codec_write(codec, ACCELCODEC_R0D, 0x10 | ASC_INPUT_VOL_0DB);
+#ifdef USE_MIC_IN
+       if (mic_vol > 0x07) {
+               /*Select MIC input*/
+               rk1000_codec_write(codec, ACCELCODEC_R12,
+                                  0x4c | ASC_MIC_INPUT | ASC_MIC_BOOST_20DB);
+               mic_vol -= 0x07;
+       } else
+               /*Select MIC input*/
+               rk1000_codec_write(codec, ACCELCODEC_R12, 0x4c | ASC_MIC_INPUT);
+       /*use default value*/
+       rk1000_codec_write(codec, ACCELCODEC_R1C, ASC_DEM_ENABLE);
+#else
+       /*Select Line input*/
+       rk1000_codec_write(codec, ACCELCODEC_R12, 0x4c);
+#endif
+       rk1000_codec_write(codec, ACCELCODEC_R0E, 0x10|mic_vol);
+       /*Diable route PGA->R/L Mixer, PGA gain 0db.*/
+       rk1000_codec_write(codec, ACCELCODEC_R13, 0x05 | 0 << 3);
+       rk1000_codec_write(codec, ACCELCODEC_R14, 0x05 | 0 << 3);
+       /*2soft mute*/
+       rk1000_codec_write(codec, ACCELCODEC_R04,
+                          ASC_INT_MUTE_L | ASC_INT_MUTE_R |
+                          ASC_SIDETONE_L_OFF | ASC_SIDETONE_R_OFF);
+       /*2set default SR and clk*/
+       rk1000_codec_write(codec, ACCELCODEC_R0A, FREQ441KHZ | ASC_NORMAL_MODE |
+                          (0x10 << 1) | ASC_CLKNODIV | ASC_CLK_ENABLE);
+       g_r0_a_reg = ASC_NORMAL_MODE | (0x10 << 1) |
+                    ASC_CLKNODIV | ASC_CLK_DISABLE;
+       /*2Config audio  interface*/
+       rk1000_codec_write(codec, ACCELCODEC_R09, ASC_I2S_MODE |
+                          ASC_16BIT_MODE | ASC_NORMAL_LRCLK |
+                          ASC_LRSWAP_DISABLE | ASC_NORMAL_BCLK);
+       rk1000_codec_write(codec, ACCELCODEC_R00, ASC_HPF_ENABLE
+                          | ASC_DSM_MODE_ENABLE | ASC_SCRAMBLE_ENABLE
+                          | ASC_DITHER_ENABLE | ASC_BCLKDIV_4);
+       /*2volume,input,output*/
+       digital_gain = VOLUME_OUTPUT;
+       if (rk1000_codec_read(codec, ACCELCODEC_R05) != 0x0f) {
+               rk1000_codec_write(codec, ACCELCODEC_R05,
+                                  (digital_gain >> 8) & 0xFF);
+               rk1000_codec_write(codec, ACCELCODEC_R06, digital_gain & 0xFF);
        }
+       if (rk1000_codec_read(codec, ACCELCODEC_R07) != 0x0f) {
+               rk1000_codec_write(codec, ACCELCODEC_R07,
+                                  (digital_gain >> 8) & 0xFF);
+               rk1000_codec_write(codec, ACCELCODEC_R08, digital_gain & 0xFF);
+       }
+       rk1000_codec_write(codec, ACCELCODEC_R0B,
+                          ASC_DEC_ENABLE | ASC_INT_ENABLE);
+       g_r0_b_reg = ASC_DEC_ENABLE | ASC_INT_ENABLE;
+       if (rk1000_codec->boot_depop) {
+               #if OUT_CAPLESS
+               rk1000_codec_write(codec, ACCELCODEC_R1F,
+                                  0x09 | ASC_PDMIXM_ENABLE);
+               #else
+               rk1000_codec_write(codec, ACCELCODEC_R1F, 0x09 |
+                                  ASC_PDMIXM_ENABLE | ASC_PDPAM_ENABLE);
+               #endif
+       }
+       rk1000_codec_write(codec, ACCELCODEC_R17, VOLUME_CODEC_PA |
+                          ASC_OUTPUT_ACTIVE | ASC_CROSSZERO_EN);
+       rk1000_codec_write(codec, ACCELCODEC_R18, VOLUME_CODEC_PA |
+                          ASC_OUTPUT_ACTIVE | ASC_CROSSZERO_EN);
+       rk1000_codec_write(codec, ACCELCODEC_R04, ASC_INT_ACTIVE_L |
+                          ASC_INT_ACTIVE_R | ASC_SIDETONE_L_OFF |
+                          ASC_SIDETONE_R_OFF);
+       rk1000_codec_write(codec, ACCELCODEC_R19, 0x7F);
+}
 
-       rk1000_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
+static int rk1000_codec_suspend(struct snd_soc_codec *codec)
+{
+       DBG("Enter::%s----%d\n", __func__, __LINE__);
+       spk_ctrl_fun(GPIO_LOW);
        return 0;
 }
 
-static void rk1000_reg_init(struct snd_soc_codec *codec)
+static int rk1000_codec_resume(struct snd_soc_codec *codec)
 {
-       rk1000_codec_write(codec,ACCELCODEC_R1D, 0x00);
-    rk1000_codec_write(codec,ACCELCODEC_R17, 0xFF);  //AOL
-    rk1000_codec_write(codec,ACCELCODEC_R18, 0xFF);  //AOR
-    rk1000_codec_write(codec,ACCELCODEC_R19, 0xFF);  //AOM
-
-    rk1000_codec_write(codec,ACCELCODEC_R1F, 0xDF);
-    mdelay(10);
-    rk1000_codec_write(codec,ACCELCODEC_R1F, 0x5F);
-    rk1000_codec_write(codec,ACCELCODEC_R19, 0x7F);  //AOM
-    rk1000_codec_write(codec,ACCELCODEC_R15, 0xC1);//rk1000_codec_write(codec,ACCELCODEC_R15, 0xCD);//by Vincent Hsiung
-    rk1000_codec_write(codec,ACCELCODEC_R1A, 0x1C);
-    mdelay(100);
-    rk1000_codec_write(codec,ACCELCODEC_R1F, 0x09);
-    rk1000_codec_write(codec,ACCELCODEC_R1E, 0x00);
-    mdelay(10);
-    rk1000_codec_write(codec,ACCELCODEC_R1A, 0x14);
-    rk1000_codec_write(codec,ACCELCODEC_R1D, 0xFE);
-    rk1000_codec_write(codec,ACCELCODEC_R17, 0xBF);  //AOL
-    rk1000_codec_write(codec,ACCELCODEC_R18, 0xBF);  //AOR
-    rk1000_codec_write(codec,ACCELCODEC_R19, 0x7F);  //AOM
-    rk1000_codec_write(codec,ACCELCODEC_R1F, 0xDF);
-
-    //2soft mute
-    rk1000_codec_write(codec,ACCELCODEC_R04, ASC_INT_MUTE_L|ASC_INT_MUTE_R|ASC_SIDETONE_L_OFF|ASC_SIDETONE_R_OFF);   //soft mute
-    
-    //2set default SR and clk
-    rk1000_codec_write(codec,ACCELCODEC_R0A, ASC_USB_MODE|FREQ48kHz|ASC_CLKNODIV|ASC_CLK_DISABLE);
-    gR0AReg = ASC_USB_MODE|FREQ48kHz|ASC_CLKNODIV|ASC_CLK_DISABLE;
-    //2Config audio  interface
-    rk1000_codec_write(codec,ACCELCODEC_R09, ASC_I2S_MODE|ASC_16BIT_MODE|ASC_NORMAL_LRCLK|ASC_LRSWAP_DISABLE|ASC_MASTER_MODE|ASC_NORMAL_BCLK);
-    rk1000_codec_write(codec,ACCELCODEC_R00, ASC_HPF_ENABLE|ASC_DSM_MODE_DISABLE|ASC_SCRAMBLE_ENABLE|ASC_DITHER_ENABLE|ASC_BCLKDIV_8);  //BCLK div 8
-    //2volume,input,outpu
-    rk1000_codec_write(codec,ACCELCODEC_R05, 0x0e);
-    rk1000_codec_write(codec,ACCELCODEC_R06, 0x42);
-    rk1000_codec_write(codec,ACCELCODEC_R07, 0x0e);
-    rk1000_codec_write(codec,ACCELCODEC_R08, 0x42);
-    
-    rk1000_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB|ASC_INPUT_MUTE);   //LIL
-    rk1000_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB);   //LIR
-    rk1000_codec_write(codec,ACCELCODEC_R0E, 0x10|ASC_INPUT_VOL_0DB);   //MIC
-    rk1000_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB);  //mic input and boost 20dB
-    rk1000_codec_write(codec,ACCELCODEC_R13, ASC_LPGAMX_DISABLE|ASC_ALMX_DISABLE|((LINE_2_MIXER_GAIN & 0x7) << 4)|0x0);
-    rk1000_codec_write(codec,ACCELCODEC_R14, ASC_RPGAMX_DISABLE|ASC_ARMX_DISABLE|((LINE_2_MIXER_GAIN & 0x7) << 4)|0x0);
-    gR1314Reg = ASC_RPGAMX_DISABLE|ASC_ARMX_DISABLE|((LINE_2_MIXER_GAIN & 0x7) << 4)|0x0;
-
-    //2other
-    rk1000_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_DISABLE);  //0x00
-    gR0BReg = ASC_DEC_DISABLE|ASC_INT_DISABLE;
-    rk1000_codec_write(codec,ACCELCODEC_R15, \
-                    0x01|ASC_RLPFMX_DISABLE|ASC_LLPFMX_DISABLE|ASC_LDAMX_DISABLE|ASC_RDAMX_DISABLE|ASC_LSCF_ACTIVE|ASC_RSCF_ACTIVE);  //0x3c
-    rk1000_codec_write(codec,ACCELCODEC_R1B, 0x32);
-    rk1000_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE);  ///0x00);  //use default value
-    
-    //dac mode
-    rk1000_codec_write(codec,ACCELCODEC_R17, 0xBF);  //AOL  ÒôÁ¿×îµÍ
-    rk1000_codec_write(codec,ACCELCODEC_R18, 0xBF);  //AOR
-        
-    //2power down useless module
-    rk1000_codec_write(codec,ACCELCODEC_R1D, 0x2a|ASC_PDSDL_ENABLE|ASC_PDBSTL_ENABLE|ASC_PDPGAL_ENABLE);  //setup Vmid and Vref, other module power down
-    rk1000_codec_write(codec,ACCELCODEC_R1E, 0x40|ASC_PDASDML_ENABLE);
-    #if OUT_CAPLESS
-    rk1000_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE);
-    #else
-    rk1000_codec_write(codec,ACCELCODEC_R1F, 0x09|ASC_PDMICB_ENABLE|ASC_PDMIXM_ENABLE|ASC_PDPAM_ENABLE);
-    #endif
-
-    //2other
-    rk1000_codec_write(codec,ACCELCODEC_R0B, ASC_DEC_DISABLE|ASC_INT_ENABLE);
-    gR0BReg = ASC_DEC_ENABLE|ASC_INT_ENABLE;  //ASC_DEC_DISABLE|ASC_INT_ENABLE;
-    rk1000_codec_write(codec,ACCELCODEC_R15, 0xC1);//rk1000_codec_write(codec,ACCELCODEC_R15, 0xCD);//by Vincent Hsiung
-    rk1000_codec_write(codec,ACCELCODEC_R0C, 0x10|ASC_INPUT_VOL_0DB|ASC_INPUT_MUTE);   //LIL
-    rk1000_codec_write(codec,ACCELCODEC_R0D, 0x10|ASC_INPUT_VOL_0DB);   //LIR
-    rk1000_codec_write(codec,ACCELCODEC_R0E, 0x10|ASC_INPUT_VOL_0DB);   //MIC
-    rk1000_codec_write(codec,ACCELCODEC_R12, 0x4c|ASC_MIC_INPUT|ASC_MIC_BOOST_20DB);  //mic input and boost 20dB
-    rk1000_codec_write(codec,ACCELCODEC_R13, 0x00);
-    rk1000_codec_write(codec,ACCELCODEC_R14, 0x00);
-    gR1314Reg = 0x00;
-    rk1000_codec_write(codec,ACCELCODEC_R1C, ASC_DEM_ENABLE);  //0x00);  //use default value
+       spk_ctrl_fun(GPIO_HIGH);
+       return 0;
 }
 
 static int rk1000_codec_probe(struct snd_soc_codec *codec)
 {
-       struct rk1000_codec_priv *rk1000_codec_priv = snd_soc_codec_get_drvdata(codec);
-
-       int ret = 0;
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
+       struct rk1000_codec_priv *rk1000_codec;
+       int ret;
 
        rk1000_codec_codec = codec;
-       
-       codec->control_data = rk1000_codec_priv->control_data;
-       
-       ret = snd_soc_codec_set_cache_io(codec, 8, 8, rk1000_codec_priv->control_type);
+       rk1000_codec = snd_soc_codec_get_drvdata(codec);
+       DBG("[%s] start\n", __func__);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16,
+                                        rk1000_codec->control_type);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
-       
-       codec->reg_cache = kmemdup(rk1000_codec_reg, sizeof(rk1000_codec_reg), GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
-
-       rk1000_reg_init(codec);
-//     snd_soc_add_codec_controls(codec, rk1000_codec_snd_controls,
-//                             ARRAY_SIZE(rk1000_codec_snd_controls));
-//     snd_soc_dapm_new_controls(codec, rk1000_codec_dapm_widgets,
-//                               ARRAY_SIZE(rk1000_codec_dapm_widgets));
-//     snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-
-
+       /*For RK1000, i2c write&read method is special
+        *do not use system default method.*/
+       codec->write = rk1000_codec_write;
+       codec->read = rk1000_codec_read;
+       codec->hw_write = (hw_write_t)i2c_master_send;
+       if (rk1000_codec_codec == NULL) {
+               dev_err(codec->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+       INIT_DELAYED_WORK(&rk1000_codec->rk1000_delayed_work,
+                         rk1000_delayedwork_fun);
+
+       if (rk1000_codec->spk_ctrl_io) {
+               ret = gpio_request(rk1000_codec->spk_ctrl_io,
+                                  "rk1000-spk-ctrl");
+               if (ret) {
+                       DBG("rk1000 codec request gpio fail!\n");
+                       return ret;
+               }
+               /*set hight disable codec lr output*/
+               gpio_direction_output(rk1000_codec->spk_ctrl_io,
+                                     !rk1000_codec->flags);
+               gpio_set_value(rk1000_codec->spk_ctrl_io,
+                              !rk1000_codec->flags);
+       }
+       rk1000_codec->call_enable = 0;
+       rk1000_codec->headset_status = HP_OUT;
+       rk1000_codec_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
+       schedule_delayed_work(&rk1000_codec->rk1000_delayed_work,
+                             msecs_to_jiffies(rk1000_codec->pa_enable_time));
+       rk1000_codec_reg_set();
+       DBG("rk1000_codec_probe ret=0x%x\n", ret);
        return ret;
 }
 
 static int rk1000_codec_remove(struct snd_soc_codec *codec)
 {
-       struct rk1000_codec_priv *rk1000_codec_priv = snd_soc_codec_get_drvdata(codec);
-
        rk1000_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       kfree(rk1000_codec_priv);
        return 0;
 }
 
 static struct snd_soc_codec_driver soc_codec_dev_rk1000_codec = {
-       .probe =        rk1000_codec_probe,
-       .remove =       rk1000_codec_remove,
-       .suspend =      rk1000_codec_suspend,
+       .probe =        rk1000_codec_probe,
+       .remove =       rk1000_codec_remove,
+       .suspend =      rk1000_codec_suspend,
        .resume =       rk1000_codec_resume,
        .set_bias_level = rk1000_codec_set_bias_level,
-       .read =         rk1000_codec_read,
-       .write =        rk1000_codec_write,
-//     .readable_register = rk1000_codec_read_reg_cache,
-//     .writable_register = rk1000_codec_write_reg_cache,
-//     .volatile_register = wm8994_volatile,   
        .reg_cache_size = ARRAY_SIZE(rk1000_codec_reg),
-       .reg_word_size = sizeof(u8),
+       .reg_word_size = sizeof(u16),
        .reg_cache_default = rk1000_codec_reg,
 };
 
-#ifdef RK1000_CODEC_PROC       
-static int rk1000_codec_proc_init(void);
-#endif
 
 static int rk1000_codec_i2c_probe(struct i2c_client *i2c,
-                           const struct i2c_device_id *id)
+                                 const struct i2c_device_id *id)
 {
        struct rk1000_codec_priv *rk1000_codec;
+       struct device_node *rk1000_np = i2c->dev.of_node;
        int ret;
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-       rk1000_codec = kzalloc(sizeof(struct rk1000_codec_priv), GFP_KERNEL);
+
+       DBG("%s::%d\n", __func__, __LINE__);
+       rk1000_codec = kmalloc(sizeof(*rk1000_codec), GFP_KERNEL);
        if (rk1000_codec == NULL)
                return -ENOMEM;
-
+       rk1000_codec->spk_ctrl_io = of_get_named_gpio_flags(rk1000_np,
+                                   "spk_ctl_io", 0, &(rk1000_codec->flags));
+       if (!gpio_is_valid(rk1000_codec->spk_ctrl_io)) {
+               DBG("invalid core_info->reset_gpio: %d\n",
+                   rk1000_codec->spk_ctrl_io);
+               return -1;
+       }
+       of_property_read_u32(rk1000_np, "pa_enable_time",
+                            &(rk1000_codec->pa_enable_time));
+       of_property_read_u32(rk1000_np, "boot_depop",
+                            &(rk1000_codec->boot_depop));
        i2c_set_clientdata(i2c, rk1000_codec);
        rk1000_codec->control_type = SND_SOC_I2C;
-       rk1000_codec->control_data = i2c;
-       
        ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rk1000_codec,
-                       rk1000_codec_dai, ARRAY_SIZE(rk1000_codec_dai));
+                                    rk1000_codec_dai,
+                                    ARRAY_SIZE(rk1000_codec_dai));
        if (ret < 0)
                kfree(rk1000_codec);
-               
-#ifdef RK1000_CODEC_PROC       
-  rk1000_codec_proc_init();
-#endif
-
        return ret;
 }
 
 static int rk1000_codec_i2c_remove(struct i2c_client *client)
 {
        snd_soc_unregister_codec(&client->dev);
-       kfree(i2c_get_clientdata(client));      
+       kfree(i2c_get_clientdata(client));
        return 0;
 }
 
 static const struct i2c_device_id rk1000_codec_i2c_id[] = {
-       { "rk1000_i2c_codec", 0 },
+       { "rk1000_codec", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, rk1000_codec_i2c_id);
@@ -913,7 +862,7 @@ MODULE_DEVICE_TABLE(i2c, rk1000_codec_i2c_id);
 /* corgi i2c codec control layer */
 static struct i2c_driver rk1000_codec_i2c_driver = {
        .driver = {
-               .name = "RK1000_CODEC",
+               .name = "rk1000_codec",
                .owner = THIS_MODULE,
        },
        .probe = rk1000_codec_i2c_probe,
@@ -924,9 +873,15 @@ static struct i2c_driver rk1000_codec_i2c_driver = {
 
 static int __init rk1000_codec_modinit(void)
 {
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-       return i2c_add_driver(&rk1000_codec_i2c_driver);
+       int ret;
+
+       DBG("[%s] start\n", __func__);
+       ret = i2c_add_driver(&rk1000_codec_i2c_driver);
+       if (ret != 0)
+               pr_err("rk1000 codec: register I2C driver err=: %d\n", ret);
+       return ret;
 }
+/* late_initcall(rk1000_codec_modinit); */
 module_init(rk1000_codec_modinit);
 
 static void __exit rk1000_codec_exit(void)
@@ -935,230 +890,136 @@ static void __exit rk1000_codec_exit(void)
 }
 module_exit(rk1000_codec_exit);
 
+
+
 #ifdef RK1000_CODEC_PROC
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static int debug_write_read;
+
 void rk1000_codec_reg_read(void)
 {
-    struct snd_soc_codec *codec = rk1000_codec_codec;
-    int i;
-    unsigned int data;
-
-    for (i=0; i<=0x1f; i++){
-        data = rk1000_codec_read(codec, i);
-        printk("reg[0x%x]=0x%x\n",i,data);
-    }
+       struct snd_soc_codec *codec;
+       int i;
+       unsigned int data;
+
+       codec = rk1000_codec_codec;
+       for (i = 0; i <= 0x1f; i++) {
+               data = rk1000_codec_read(codec, i);
+               pr_info("reg[0x%x]=0x%x\n", i, data);
+       }
 }
 
-static ssize_t rk1000_codec_proc_write(struct file *file, const char __user *buffer,
-                          unsigned long len, void *data)
+
+static ssize_t rk1000_codec_proc_write(struct file *file,
+                                      const char __user *buffer,
+                                      size_t len, loff_t *data)
 {
-       char *cookie_pot; 
+       char *cookie_pot;
        char *p;
-       int reg;
-       int value;
-       
-       cookie_pot = (char *)vmalloc( len );
-       if (!cookie_pot) 
-       {
+       long reg;
+       long value;
+       int ret;
+
+       cookie_pot = vmalloc(len);
+       if (!cookie_pot) {
+               pr_err("malloc cookie error for rk1000 codec proc debug\n");
                return -ENOMEM;
-       } 
-       else 
-       {
-               if (copy_from_user( cookie_pot, buffer, len )) 
+       } else {
+               if (copy_from_user(cookie_pot, buffer, len))
                        return -EFAULT;
        }
-
-       switch(cookie_pot[0])
-       {
+       switch (cookie_pot[0]) {
        case 'd':
        case 'D':
-               debug_write_read ++;
+               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;  
+               if (debug_write_read != 0)
+                       pr_info("Debug read and write reg on\n");
+               else
+                       pr_info("Debug read and write reg off\n");
+               break;
        case 'r':
        case 'R':
-               printk("Read reg debug\n");             
-               if(cookie_pot[1] ==':')
-               {
+               pr_info("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 = rk1000_codec_read(rk1000_codec_codec,reg);
-                               printk("rk1000_codec_read:0x%04x = 0x%04x",reg,value);
+                       strsep(&cookie_pot, ":");
+                       while ((p = strsep(&cookie_pot, ","))) {
+                               ret = kstrtol((const char *)p, 0, &reg);
+                               if (ret < 0) {
+                                       pr_err("string to long error\n");
+                                       return ret;
+                               }
+                               value = rk1000_codec_read(rk1000_codec_codec,
+                                                         reg);
+                               pr_info("rk1000_codec_read:0x%04lx = 0x%04lx",
+                                       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");
+                       pr_info("\n");
+               } else {
+                       pr_info("Error Read reg debug.\n");
                }
                break;
        case 'w':
        case 'W':
-               printk("Write reg debug\n");            
-               if(cookie_pot[1] ==':')
-               {
+               pr_info("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);
-                               rk1000_codec_write(rk1000_codec_codec,reg,value);
-                               printk("rk1000_codec_write:0x%04x = 0x%04x\n",reg,value);
+                       strsep(&cookie_pot, ":");
+                       while ((p = strsep(&cookie_pot, "="))) {
+                               ret = kstrtol(p, 0, &reg);
+                               if (ret < 0) {
+                                       pr_err("string to long error\n");
+                                       return ret;
+                               }
+                               p = strsep(&cookie_pot, ",");
+                               ret = kstrtol(p, 0, &value);
+                               if (ret < 0) {
+                                       pr_err("string to long error\n");
+                                       return ret;
+                               }
+                               rk1000_codec_write(rk1000_codec_codec, reg,
+                                                  value);
+                               pr_info("rk1000_codec_write:0x%04lx = 0x%04lx\n",
+                                       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");
+                       pr_info("\n");
+               } else {
+                       pr_info("Error Write reg debug.\n");
+                       pr_info("For example: w:22=0,23=0,24=0,25=0\n");
                }
                break;
-       case 'p'://enable pa
+       case 'p':
                rk1000_codec_reg_read();
                break;
        default:
-               printk("Help for rk1000_codec_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'>rk1000_codec_ts\n");
-               printk("-->'w&&W' Write reg debug,Example: echo 'w:22=0,23=0,24=0,25=0'>rk1000_codec_ts\n");
+               pr_info("Help for rk1000_codec_ts .\n-->The Cmd list:\n");
+               pr_info("-->'d&&D' Open or Off the debug\n");
+               pr_info("-->'r&&R' Read reg debug,Example:");
+               pr_info("echo 'r:22,23,24,25'>rk1000_codec_ts\n");
+               pr_info("-->'w&&W' Write reg debug,Example:");
+               pr_info("echo 'w:22=0,23=0,24=0,25=0'>rk1000_codec_ts\n");
                break;
        }
-
+       vfree(cookie_pot);
        return len;
 }
+
+
 static const struct file_operations rk1000_codec_proc_fops = {
-       .owner          = THIS_MODULE,
-       //.open         = snd_mem_proc_open,
-       //.read         = seq_read,
-//#ifdef CONFIG_PCI
-//     .write          = rk1000_codec_proc_write,
-//#endif
-       //.llseek       = seq_lseek,
-       //.release      = single_release,
+       .owner = THIS_MODULE,
+       .write = rk1000_codec_proc_write,
 };
 
 static int rk1000_codec_proc_init(void)
 {
-       struct proc_dir_entry *rk1000_codec_proc_entry;
-       rk1000_codec_proc_entry = create_proc_entry("driver/rk1000_codec", 0777, NULL);
-       if(rk1000_codec_proc_entry != NULL)
-       {
-               rk1000_codec_proc_entry->write_proc = rk1000_codec_proc_write;
-               return -1;
-       }
-       else
-       {
-               printk("create rk1000_codec proc error !\n");
-       }
-       return 0;
-}
-
-#endif
-
-#if 1
-int reg_send_data(struct i2c_client *client, const char start_reg,
-                               const char *buf, int count, unsigned int scl_rate)
-{
-       int ret;
-       struct i2c_adapter *adap = client->adapter;
-       struct i2c_msg msg;
-       char tx_buf[count + 1];
-                                           
-       tx_buf[0] = start_reg;
-       memcpy(tx_buf+1, buf, count); 
-  
-       msg.addr = client->addr;
-       msg.buf = tx_buf;
-       msg.len = count +1;
-       msg.flags = client->flags;   
-       msg.scl_rate = scl_rate;
-                                                                                                   
-       ret = i2c_transfer(adap, &msg, 1);
-
-       return ret;    
-}
-
-static int rk1000_control_probe(struct i2c_client *client,
-                       const struct i2c_device_id *id)
-{
-       int ret;
-       char data[4] = {0x88, 0x0d, 0x22, 0x00};
-//     reg[0x00] = 0x88, --> ADC_CON
-//     reg[0x01] = 0x0d, --> CODEC_CON
-//     reg[0x02] = 0x22, --> I2C_CON
-//     reg[0x03] = 0x00, --> TVE_CON
-       #ifdef CONFIG_SND_SOC_RK1000
-    data[1] = 0x00;
-    #endif
-       
-       DBG("%s::%d\n",__FUNCTION__,__LINE__);
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
-       {
-               dev_err(&client->dev, "i2c bus does not support the rk1000_control\n");
-               return -EIO;
-       }
-       
-       msleep(50);
-       ret = reg_send_data(client, 0x00, data, 4, 100 * 1000);
-#if 1
-    printk("i2c write ret = 0x%x\n",ret);
-       memset(data,0,sizeof(data));
-       ret = i2c_master_recv(client, data, 4);
-    //ret = i2c_master_reg8_recv(client, 0, data, (int)4, 20*1000);
-    printk("i2c read reg    %x,   %x,   %x,  %x   ret=x%x\n",data[0],data[1],data[2],data[3],ret);
-#endif
-       
-       if (ret > 0)
-               ret = 0;
-
-       return ret;     
-}
-
-static int rk1000_control_remove(struct i2c_client *client)
-{
+       proc_create("rk1000_codec_reg", 0,
+                   NULL, &rk1000_codec_proc_fops);
        return 0;
 }
-
-static const struct i2c_device_id rk1000_control_id[] = {
-       { "rk1000_control", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, rk1000_control_id);
-
-static struct i2c_driver rk1000_control_driver = {
-       .driver = {
-               .name = "rk1000_control",
-       },
-       .probe = rk1000_control_probe,
-       .remove = rk1000_control_remove,
-       .id_table = rk1000_control_id,
-};
-
-static int __init rk1000_control_init(void)
-{
-       return i2c_add_driver(&rk1000_control_driver);
-}
-
-static void __exit rk1000_control_exit(void)
-{
-       i2c_del_driver(&rk1000_control_driver);
-}
-
-module_init(rk1000_control_init);
-module_exit(rk1000_control_exit);
-
-MODULE_DESCRIPTION("ASoC RK1000 CODEC driver");
-MODULE_AUTHOR("lhh lhh@rock-chips.com");
-MODULE_LICENSE("GPL");
+late_initcall(rk1000_codec_proc_init);
 #endif
index 817219903b8b98fc4b812a7cc8f52cf2ca12495a..8340e90fc1d02658033cc46715c7692036526ce3 100755 (executable)
 
 /* RK1000 register space */
 
-#define      ACCELCODEC_R00    0x00    //ADC High Pass Filter / DSM
-#define      ACCELCODEC_R01    0x01    //DITHER power
-#define      ACCELCODEC_R02    0x02    //DITHER power
-#define      ACCELCODEC_R03    0x03    //DITHER power
-#define      ACCELCODEC_R04    0x04    //Soft mute / sidetone gain control
-#define      ACCELCODEC_R05    0x05    //Right interpolate filter volume control (MSB)
-#define      ACCELCODEC_R06    0x06    //Right interpolate filter volume control (LSB)
-#define      ACCELCODEC_R07    0x07    //Left interpolate filter volume control (MSB)
-#define      ACCELCODEC_R08    0x08    //Left interpolate filter volume control (LSB)
-#define      ACCELCODEC_R09    0x09    //Audio interface control
-#define      ACCELCODEC_R0A    0x0A    //Sample Rate / CLK control
-#define      ACCELCODEC_R0B    0x0B    //Decimation filter / Interpolate filter enable
-#define      ACCELCODEC_R0C    0x0C    //LIN volume
-#define      ACCELCODEC_R0D    0x0D    //LIP volume
-#define      ACCELCODEC_R0E    0x0E    //AL volume
-//#define      ACCELCODEC_R0F    0x0F    //RIN volume
-//#define      ACCELCODEC_R10    0x10    //RIP volume
-//#define      ACCELCODEC_R11    0x11    //AR volume
-#define      ACCELCODEC_R12    0x12    //Input volume
-#define      ACCELCODEC_R13    0x13    //Left out mix
-#define      ACCELCODEC_R14    0x14    //Right out mix
-#define      ACCELCODEC_R15    0x15    //LPF out mix / SCF
-#define      ACCELCODEC_R16    0x16    //SCF control
-#define      ACCELCODEC_R17    0x17    //LOUT (AOL) volume
-#define      ACCELCODEC_R18    0x18    //ROUT (AOR) volume
-#define      ACCELCODEC_R19    0x19    //MONOOUT (AOM) volume
-#define      ACCELCODEC_R1A    0x1A    //MONOOUT / Reference control
-#define      ACCELCODEC_R1B    0x1B    //Bias Current control
-#define      ACCELCODEC_R1C    0x1C    //ADC control
-#define      ACCELCODEC_R1D    0x1D    //Power Mrg 1
-#define      ACCELCODEC_R1E    0x1E    //Power Mrg 2
-#define      ACCELCODEC_R1F    0x1F    //Power Mrg 3
+/* ADC High Pass Filter / DSM */
+#define        ACCELCODEC_R00  0x00
+/* DITHER power */
+#define        ACCELCODEC_R01  0x01
+/* DITHER power */
+#define        ACCELCODEC_R02  0x02
+/* DITHER power */
+#define        ACCELCODEC_R03  0x03
+/* Soft mute / sidetone gain control */
+#define        ACCELCODEC_R04  0x04
+/* Right interpolate filter volume control (MSB) */
+#define        ACCELCODEC_R05  0x05
+/* Right interpolate filter volume control (LSB) */
+#define        ACCELCODEC_R06  0x06
+/* Left interpolate filter volume control (MSB) */
+#define        ACCELCODEC_R07  0x07
+/* Left interpolate filter volume control (LSB) */
+#define        ACCELCODEC_R08  0x08
+/* Audio interface control */
+#define        ACCELCODEC_R09  0x09
+/* Sample Rate / CLK control */
+#define        ACCELCODEC_R0A  0x0A
+/* Decimation filter / Interpolate filter enable */
+#define        ACCELCODEC_R0B  0x0B
+/* LIN volume */
+#define        ACCELCODEC_R0C  0x0C
+/* LIP volume */
+#define        ACCELCODEC_R0D  0x0D
+/* AL volume */
+#define        ACCELCODEC_R0E  0x0E
+/* Input volume */
+#define        ACCELCODEC_R12  0x12
+/* Left out mix */
+#define        ACCELCODEC_R13  0x13
+/* Right out mix */
+#define        ACCELCODEC_R14  0x14
+/* LPF out mix / SCF */
+#define        ACCELCODEC_R15  0x15
+/* SCF control */
+#define        ACCELCODEC_R16  0x16
+/* LOUT (AOL) volume */
+#define        ACCELCODEC_R17  0x17
+/* ROUT (AOR) volume */
+#define        ACCELCODEC_R18  0x18
+/* MONOOUT (AOM) volume */
+#define        ACCELCODEC_R19  0x19
+/* MONOOUT / Reference control */
+#define        ACCELCODEC_R1A  0x1A
+/* Bias Current control */
+#define        ACCELCODEC_R1B  0x1B
+/* ADC control */
+#define        ACCELCODEC_R1C  0x1C
+/* Power Mrg 1 */
+#define        ACCELCODEC_R1D  0x1D
+/* Power Mrg 2 */
+#define        ACCELCODEC_R1E  0x1E
+/* Power Mrg 3 */
+#define        ACCELCODEC_R1F  0x1F
 
 #define      RK1000_CACHE_REGNUM  0x1F
 
-//ACCELCODEC_R00
-#define ASC_HPF_ENABLE               (0x1)    //high_pass filter
-#define ASC_HPF_DISABLE              (0x0)
+/* ACCELCODEC_R00 */
+/* high_pass filter */
+#define ASC_HPF_ENABLE (0x1)
+#define ASC_HPF_DISABLE        (0x0)
 
-#define ASC_DSM_MODE_ENABLE          (0x1 << 1)
-#define ASC_DSM_MODE_DISABLE         (0x0 << 1)
-
-#define ASC_SCRAMBLE_ENABLE          (0x1 << 2)
-#define ASC_SCRAMBLE_DISABLE         (0x0 << 2)
-
-#define ASC_DITHER_ENABLE            (0x1 << 3)
-#define ASC_DITHER_DISABLE           (0x0 << 3)
-
-#define ASC_BCLKDIV_4                (0x1 << 4)
-#define ASC_BCLKDIV_8                (0x2 << 4)
-#define ASC_BCLKDIV_16               (0x3 << 4)
-
-//ACCECODEC_R04
-#define ASC_INT_MUTE_L               (0x1)
-#define ASC_INT_ACTIVE_L             (0x0)
-#define ASC_INT_MUTE_R               (0x1 << 1)
-#define ASC_INT_ACTIVE_R             (0x0 << 1)
-
-#define ASC_SIDETONE_L_OFF           (0x0 << 2)
-#define ASC_SIDETONE_L_GAIN_MAX      (0x1 << 2)
-#define ASC_SIDETONE_R_OFF           (0x0 << 5)
-#define ASC_SIDETONE_R_GAIN_MAX      (0x1 << 5)
-
-
-//ACCELCODEC_R05
-#define ASC_INT_VOL_0DB              (0x0)
-
-
-//ACCELCODEC_R09
-#define ASC_DSP_MODE                 (0x3)
-#define ASC_I2S_MODE                 (0x2)
-#define ASC_LEFT_MODE                (0x1)
-//#define ASC_RIGHT_MODE               (0x0)
-
-#define ASC_32BIT_MODE               (0x3 << 2)
-#define ASC_24BIT_MODE               (0x2 << 2)
-#define ASC_20BIT_MODE               (0x1 << 2)
-#define ASC_16BIT_MODE               (0x0 << 2)
-
-#define ASC_INVERT_LRCLK             (0x1 << 4)
-#define ASC_NORMAL_LRCLK             (0x0 << 4)
-
-#define ASC_LRSWAP_ENABLE            (0x1 << 5)
-#define ASC_LRSWAP_DISABLE           (0x0 << 5)
-
-#define ASC_MASTER_MODE              (0x1 << 6)
-#define ASC_SLAVE_MODE               (0x0 << 6)
-
-#define ASC_INVERT_BCLK              (0x1 << 7)
-#define ASC_NORMAL_BCLK              (0x0 << 7)
-
-//ACCELCODEC_R0A
-#define ASC_USB_MODE                 (0x1)
-#define ASC_NORMAL_MODE              (0x0)
-
-#define FREQ96kHz                    (0x0e << 1)
-#define FREQ48kHz                    (0x00 <<  1)
-#define FREQ441kHz                   (0x11 << 1)
-#define FREQ32kHz                    (0x0c << 1)
-#define FREQ24kHz                    (0x1c << 1)
-#define FREQ2205kHz                  (0x1B << 1)
-#define FREQ16kHz                    (0x0a << 1)
-#define FREQ12kHz                    (0x08 << 1)
-#define FREQ11025kHz                 (0x19 << 1)
-//#define   FREQ9k6Hz            0x09
-#define FREQ8kHz                     (0x06<<1)
-
-#define ASC_CLKDIV2                  (0x1 << 6)
-#define ASC_CLKNODIV                 (0x0 << 6)
-
-#define ASC_CLK_ENABLE               (0x1 << 7)
-#define ASC_CLK_DISABLE              (0x0 << 7)
-
-//ACCELCODEC_R0B
-#define ASC_DEC_ENABLE               (0x1)     //decimation filter enable
-#define ASC_DEC_DISABLE              (0x0)
-#define ASC_INT_ENABLE               (0x1 << 1)    //interpolate filter enable
-#define ASC_INT_DISABLE              (0x0 << 1)
-
-//Input
-#define ASC_INPUT_MUTE               (0x1 << 7)
-#define ASC_INPUT_ACTIVE             (0x0 << 7)
-#define ASC_INPUT_VOL_0DB            (0x0)
-
-//ACCELCODEC_R12
-#define ASC_LINE_INPUT               (0)
-#define ASC_MIC_INPUT                (1 << 7)
-
-#define ASC_MIC_BOOST_0DB            (0)
-#define ASC_MIC_BOOST_20DB           (1 << 5)
-
-//ACCELCODEC_R13
-#define ASC_LPGAMXVOL_0DB            (0x5)
-#define ASC_LPGAMX_ENABLE            (0x1 << 3)  //the left channel PGA output is directly fed into the left mixer
-#define ASC_LPGAMX_DISABLE           (0x0 << 3)
-#define ASC_ALMXVOL_0DB              (0x5 << 4)
-#define ASC_ALMX_ENABLE              (0x1 << 7)  //the left second line input is directly fed into the left mixer
-#define ASC_ALMX_DISABLE             (0x0 << 7)
-
-//ACCELCODEC_R14
-#define ASC_RPGAMXVOL_0DB            (0x5)
-#define ASC_RPGAMX_ENABLE            (0x1 << 3)  //the right channel PGA output is directly fed into the right mixer
-#define ASC_RPGAMX_DISABLE           (0x0 << 3)
-#define ASC_ARMXVOL_0DB              (0x5 << 4)
-#define ASC_ARMX_ENABLE              (0x1 << 7)  //)the right second line input is directly fed into the right mixer
-#define ASC_ARMX_DISABLE             (0x0 << 7)
-
-//ACCELCODEC_R15
-#define ASC_LDAMX_ENABLE             (0x1 << 2)  //the left differential signal from DAC is directly fed into the left mixer
-#define ASC_LDAMX_DISABLE            (0x0 << 2)
-#define ASC_RDAMX_ENABLE             (0x1 << 3)  //the right differential signal from DAC is directly fed into the right mixer
-#define ASC_RDAMX_DISABLE            (0x0 << 3)
-#define ASC_LSCF_MUTE                (0x1 << 4)  //the left channel LPF is mute
-#define ASC_LSCF_ACTIVE              (0x0 << 4)
-#define ASC_RSCF_MUTE                (0x1 << 5)  //the right channel LPF is mute
-#define ASC_RSCF_ACTIVE              (0x0 << 5)
-#define ASC_LLPFMX_ENABLE            (0x1 << 6)  //the left channel LPF output is fed into the left into the mixer
-#define ASC_LLPFMX_DISABLE           (0x0 << 6)
-#define ASC_RLPFMX_ENABLE            (0x1 << 7)  //the right channel LPF output is fed into the right into the mixer.
-#define ASC_RLPFMX_DISABLE           (0x0 << 7)
-
-//ACCELCODEC_R17/R18
-#define ASC_OUTPUT_MUTE              (0x1 << 6)
-#define ASC_OUTPUT_ACTIVE            (0x0 << 6)
-#define ASC_CROSSZERO_EN             (0x1 << 7)
-#define ASC_OUTPUT_VOL_0DB           (0x0F)
-//ACCELCODEC_R19
-#define ASC_MONO_OUTPUT_MUTE         (0x1 << 7)
-#define ASC_MONO_OUTPUT_ACTIVE       (0x0 << 7)
-#define ASC_MONO_CROSSZERO_EN        (0x1 << 6)
-
-//ACCELCODEC_R1A
-#define ASC_VMDSCL_SLOWEST           (0x0 << 2)
-#define ASC_VMDSCL_SLOW              (0x1 << 2)
-#define ASC_VMDSCL_FAST              (0x2 << 2)
-#define ASC_VMDSCL_FASTEST           (0x3 << 2)
-
-#define ASC_MICBIAS_09               (0x1 << 4)
-#define ASC_MICBIAS_06               (0x0 << 4)
-
-#define ASC_L2M_ENABLE               (0x1 << 5)  //the right channel LPF output is fed to mono PA
-#define ASC_L2M_DISABLE              (0x0 << 5)
-#define ASC_R2M_ENABLE               (0x1 << 6)  //the left channel LPF output is fed to mono PA
-#define ASC_R2M_DISABLE              (0x0 << 6)
-#define ASC_CAPLESS_ENABLE           (0x1 << 7)  //the capless connection is enable
-#define ASC_CAPLESS_DISABLE          (0x0 << 7)
-
-//ACCELCODEC_R1C
-#define ASC_DITH_0_DIV               (0x0 << 3)  //the amplitude setting of the ASDM dither(div=vdd/48)
-#define ASC_DITH_2_DIV               (0x1 << 3)
-#define ASC_DITH_4_DIV               (0x2 << 3)
-#define ASC_DITH_8_DIV               (0x3 << 3)
-
-#define ASC_DITH_ENABLE              (0x1 << 5)  //the ASDM dither is enabled
-#define ASC_DITH_DISABLE             (0x0 << 5)
-
-#define ASC_DEM_ENABLE               (0x1 << 7)  //the ASDM DEM is enabled
-#define ASC_DEM_DISABLE              (0x0 << 7)
-
-//ACCELCODEC_R1D
-#define ASC_PDVMID_ENABLE            (0x1)  //the VMID reference is powered down. VMID is connected to GND
-#define ASC_PDVMID_DISABLE           (0x0)
-#define ASC_PDSDL_ENABLE             (0x1 << 2)  //the PGA S2D buffer is power down
-#define ASC_PDSDL_DISABLE            (0x0 << 2)
-#define ASC_PDBSTL_ENABLE            (0x1 << 4)  //the micphone input Op-Amp is power down
-#define ASC_PDBSTL_DISABLE           (0x0 << 4)
-#define ASC_PDPGAL_ENABLE            (0x1 << 6)  //the PGA is power down
-#define ASC_PDPGAL_DISABLE           (0x0 << 6)
-#define ASC_PDREF_ENABLE             (0x1 << 7)  //reference generator is power down
-#define ASC_PDREF_DISABLE            (0x0 << 7)
-
-//ACCELCODEC_R1E
-#define ASC_PDPAR_ENABLE             (0x1)  //the right channel PA is power down
-#define ASC_PDPAR_DISABLE            (0x0)
-#define ASC_PDPAL_ENABLE             (0x1 << 1)  //the left channel power amplifier is power down
-#define ASC_PDPAL_DISABLE            (0x0 << 1)
-#define ASC_PDMIXR_ENABLE            (0x1 << 2)  //the right mixer is power down
-#define ASC_PDMIXR_DISABLE           (0x0 << 2)
-#define ASC_PDMIXL_ENABLE            (0x1 << 3)  //the left mixer is power down
-#define ASC_PDMIXL_DISABLE           (0x0 << 3)
-#define ASC_PDLPFR_ENABLE            (0x1 << 4)  //the right RC LPF is power down
-#define ASC_PDLPFR_DISABLE           (0x0 << 4)
-#define ASC_PDLPFL_ENABLE            (0x1 << 5)  //the left channel RC LPF is power down
-#define ASC_PDLPFL_DISABLE           (0x0 << 5)
-#define ASC_PDASDML_ENABLE           (0x1 << 7)  //the ASDM is power down
-#define ASC_PDASDML_DISABLE          (0x0 << 7)
-
-//ACCELCODEC_R1F
-#define ASC_PDSCFR_ENABLE            (0x1 << 1)  //the right channel DAC is power down
-#define ASC_PDSCFR_DISABLE           (0x0 << 1)
-#define ASC_PDSCFL_ENABLE            (0x1 << 2)  //the left channel DAC is power down
-#define ASC_PDSCFL_DISABLE           (0x0 << 2)
-#define ASC_PDMICB_ENABLE            (0x1 << 4)  //the micbias is power down
-#define ASC_PDMICB_DISABLE           (0x0 << 4)
-#define ASC_PDIB_ENABLE              (0x1 << 5)  //the left channel LPF is power down
-#define ASC_PDIB_DISABLE             (0x0 << 5)
-#define ASC_PDMIXM_ENABLE            (0x1 << 6)  //the mon mixer is power down
-#define ASC_PDMIXM_DISABLE           (0x0 << 6)
-#define ASC_PDPAM_ENABLE             (0x1 << 7)  //the mono PA is power down.
-#define ASC_PDPAM_DISABLE            (0x0 << 7)
-
-#define LINE_2_MIXER_GAIN      (0x5)    //left and right PA gain
-#define RK1000_CODEC_NUM_REG   0x20
-
-//extern struct snd_soc_dai rk1000_codec_dai;
-//extern struct snd_soc_codec_device soc_codec_dev_rk1000_codec;
+#define ASC_DSM_MODE_ENABLE    (0x1 << 1)
+#define ASC_DSM_MODE_DISABLE   (0x0 << 1)
+
+#define ASC_SCRAMBLE_ENABLE    (0x1 << 2)
+#define ASC_SCRAMBLE_DISABLE   (0x0 << 2)
+
+#define ASC_DITHER_ENABLE      (0x1 << 3)
+#define ASC_DITHER_DISABLE     (0x0 << 3)
+
+#define ASC_BCLKDIV_4  (0x1 << 4)
+#define ASC_BCLKDIV_8  (0x2 << 4)
+#define ASC_BCLKDIV_16 (0x3 << 4)
+
+/* ACCECODEC_R04 */
+#define ASC_INT_MUTE_L (0x1)
+#define ASC_INT_ACTIVE_L       (0x0)
+#define ASC_INT_MUTE_R (0x1 << 1)
+#define ASC_INT_ACTIVE_R       (0x0 << 1)
+
+#define ASC_SIDETONE_L_OFF     (0x0 << 2)
+#define ASC_SIDETONE_L_GAIN_MAX        (0x1 << 2)
+#define ASC_SIDETONE_R_OFF     (0x0 << 5)
+#define ASC_SIDETONE_R_GAIN_MAX        (0x1 << 5)
+
+
+/* ACCELCODEC_R05 */
+#define ASC_INT_VOL_0DB        (0x0)
+
+
+/* ACCELCODEC_R09 */
+#define ASC_DSP_MODE   (0x3)
+#define ASC_I2S_MODE   (0x2)
+#define ASC_LEFT_MODE  (0x1)
+#define ASC_RIGHT_MODE (0x0)
+
+#define ASC_32BIT_MODE (0x3 << 2)
+#define ASC_24BIT_MODE (0x2 << 2)
+#define ASC_20BIT_MODE (0x1 << 2)
+#define ASC_16BIT_MODE (0x0 << 2)
+
+#define ASC_INVERT_LRCLK       (0x1 << 4)
+#define ASC_NORMAL_LRCLK       (0x0 << 4)
+
+#define ASC_LRSWAP_ENABLE      (0x1 << 5)
+#define ASC_LRSWAP_DISABLE     (0x0 << 5)
+
+#define ASC_MASTER_MODE        (0x1 << 6)
+#define ASC_SLAVE_MODE (0x0 << 6)
+
+#define ASC_INVERT_BCLK        (0x1 << 7)
+#define ASC_NORMAL_BCLK        (0x0 << 7)
+
+/* ACCELCODEC_R0A */
+#define ASC_USB_MODE   (0x1)
+#define ASC_NORMAL_MODE        (0x0)
+
+#define FREQ96kHz      (0x0e << 1)
+#define FREQ48kHz      (0x00 <<  1)
+#define FREQ441kHz     (0x11 << 1)
+#define FREQ32kHz      (0x0c << 1)
+#define FREQ24kHz      (0x1c << 1)
+#define FREQ2205kHz    (0x1B << 1)
+#define FREQ16kHz      (0x0a << 1)
+#define FREQ12kHz      (0x08 << 1)
+#define FREQ11025kHz   (0x19 << 1)
+#define FREQ8kHz       (0x06<<1)
+
+#define ASC_CLKDIV2    (0x1 << 6)
+#define ASC_CLKNODIV   (0x0 << 6)
+
+#define ASC_CLK_ENABLE (0x1 << 7)
+#define ASC_CLK_DISABLE        (0x0 << 7)
+
+/* ACCELCODEC_R0B */
+#define ASC_DEC_ENABLE (0x1)
+#define ASC_DEC_DISABLE        (0x0)
+#define ASC_INT_ENABLE (0x1 << 1)
+#define ASC_INT_DISABLE        (0x0 << 1)
+
+#define ASC_INPUT_MUTE (0x1 << 7)
+#define ASC_INPUT_ACTIVE       (0x0 << 7)
+#define ASC_INPUT_VOL_0DB      (0x0)
+
+/* ACCELCODEC_R12 */
+#define ASC_LINE_INPUT (0)
+#define ASC_MIC_INPUT  (1 << 7)
+
+#define ASC_MIC_BOOST_0DB      (0)
+#define ASC_MIC_BOOST_20DB     (1 << 5)
+
+/* ACCELCODEC_R13 */
+#define ASC_LPGAMXVOL_0DB      (0x5)
+/* the left channel PGA output is directly fed into the left mixer */
+#define ASC_LPGAMX_ENABLE      (0x1 << 3)
+#define ASC_LPGAMX_DISABLE     (0x0 << 3)
+#define ASC_ALMXVOL_0DB        (0x5 << 4)
+/* the left second line input is directly fed into the left mixer */
+#define ASC_ALMX_ENABLE        (0x1 << 7)
+#define ASC_ALMX_DISABLE       (0x0 << 7)
+
+/* ACCELCODEC_R14 */
+#define ASC_RPGAMXVOL_0DB      (0x5)
+/* the right channel PGA output is directly fed into the right mixer */
+#define ASC_RPGAMX_ENABLE      (0x1 << 3)
+#define ASC_RPGAMX_DISABLE     (0x0 << 3)
+#define ASC_ARMXVOL_0DB        (0x5 << 4)
+/* the right second line input is directly fed into the right mixer */
+#define ASC_ARMX_ENABLE        (0x1 << 7)
+#define ASC_ARMX_DISABLE       (0x0 << 7)
+
+/*ACCELCODEC_R15 */
+/*the left differential signal from DAC is directly fed into the left mixer*/
+#define ASC_LDAMX_ENABLE       (0x1 << 2)
+#define ASC_LDAMX_DISABLE      (0x0 << 2)
+/* the right differential signal from DAC is *
+* directly fed into the right mixer */
+#define ASC_RDAMX_ENABLE       (0x1 << 3)
+#define ASC_RDAMX_DISABLE      (0x0 << 3)
+/* the left channel LPF is mute */
+#define ASC_LSCF_MUTE  (0x1 << 4)
+#define ASC_LSCF_ACTIVE        (0x0 << 4)
+/* the right channel LPF is mute */
+#define ASC_RSCF_MUTE  (0x1 << 5)
+#define ASC_RSCF_ACTIVE        (0x0 << 5)
+/* the left channel LPF output is fed into the left into the mixer */
+#define ASC_LLPFMX_ENABLE      (0x1 << 6)
+#define ASC_LLPFMX_DISABLE     (0x0 << 6)
+/* the right channel LPF output is fed into the right into the mixer. */
+#define ASC_RLPFMX_ENABLE      (0x1 << 7)
+#define ASC_RLPFMX_DISABLE     (0x0 << 7)
+
+/* ACCELCODEC_R17/R18 */
+#define ASC_OUTPUT_MUTE        (0x1 << 6)
+#define ASC_OUTPUT_ACTIVE      (0x0 << 6)
+#define ASC_CROSSZERO_EN       (0x1 << 7)
+#define ASC_OUTPUT_VOL_0DB     (0x0F)
+/* ACCELCODEC_R19 */
+#define ASC_MONO_OUTPUT_MUTE   (0x1 << 7)
+#define ASC_MONO_OUTPUT_ACTIVE (0x0 << 7)
+#define ASC_MONO_CROSSZERO_EN  (0x1 << 6)
+
+/* ACCELCODEC_R1A */
+#define ASC_VMDSCL_SLOWEST     (0x0 << 2)
+#define ASC_VMDSCL_SLOW        (0x1 << 2)
+#define ASC_VMDSCL_FAST        (0x2 << 2)
+#define ASC_VMDSCL_FASTEST     (0x3 << 2)
+
+#define ASC_MICBIAS_09 (0x1 << 4)
+#define ASC_MICBIAS_06 (0x0 << 4)
+
+/* the right channel LPF output is fed to mono PA */
+#define ASC_L2M_ENABLE (0x1 << 5)
+#define ASC_L2M_DISABLE        (0x0 << 5)
+/* the left channel LPF output is fed to mono PA */
+#define ASC_R2M_ENABLE (0x1 << 6)
+#define ASC_R2M_DISABLE        (0x0 << 6)
+/* the capless connection is enable */
+#define ASC_CAPLESS_ENABLE     (0x1 << 7)
+#define ASC_CAPLESS_DISABLE    (0x0 << 7)
+
+/* ACCELCODEC_R1C */
+/* the amplitude setting of the ASDM dither(div=vdd/48) */
+#define ASC_DITH_0_DIV (0x0 << 3)
+#define ASC_DITH_2_DIV (0x1 << 3)
+#define ASC_DITH_4_DIV (0x2 << 3)
+#define ASC_DITH_8_DIV (0x3 << 3)
+
+/* the ASDM dither is enabled */
+#define ASC_DITH_ENABLE        (0x1 << 5)
+#define ASC_DITH_DISABLE       (0x0 << 5)
+
+/* the ASDM DEM is enabled */
+#define ASC_DEM_ENABLE (0x1 << 7)
+#define ASC_DEM_DISABLE        (0x0 << 7)
+
+/* ACCELCODEC_R1D */
+/* the VMID reference is powered down. VMID is connected to GND */
+#define ASC_PDVMID_ENABLE      (0x1)
+#define ASC_PDVMID_DISABLE     (0x0)
+/* the PGA S2D buffer is power down */
+#define ASC_PDSDL_ENABLE       (0x1 << 2)
+#define ASC_PDSDL_DISABLE      (0x0 << 2)
+/* the micphone input Op-Amp is power down */
+#define ASC_PDBSTL_ENABLE      (0x1 << 4)
+#define ASC_PDBSTL_DISABLE     (0x0 << 4)
+/* the PGA is power down */
+#define ASC_PDPGAL_ENABLE      (0x1 << 6)
+#define ASC_PDPGAL_DISABLE     (0x0 << 6)
+/* reference generator is power down */
+#define ASC_PDREF_ENABLE       (0x1 << 7)
+#define ASC_PDREF_DISABLE      (0x0 << 7)
+
+/* ACCELCODEC_R1E */
+/* the right channel PA is power down */
+#define ASC_PDPAR_ENABLE       (0x1)
+#define ASC_PDPAR_DISABLE      (0x0)
+/* the left channel power amplifier is power down */
+#define ASC_PDPAL_ENABLE       (0x1 << 1)
+#define ASC_PDPAL_DISABLE      (0x0 << 1)
+/* the right mixer is power down */
+#define ASC_PDMIXR_ENABLE      (0x1 << 2)
+#define ASC_PDMIXR_DISABLE     (0x0 << 2)
+/* the left mixer is power down */
+#define ASC_PDMIXL_ENABLE      (0x1 << 3)
+#define ASC_PDMIXL_DISABLE     (0x0 << 3)
+/* the right RC LPF is power down */
+#define ASC_PDLPFR_ENABLE      (0x1 << 4)
+#define ASC_PDLPFR_DISABLE     (0x0 << 4)
+/* the left channel RC LPF is power down */
+#define ASC_PDLPFL_ENABLE      (0x1 << 5)
+#define ASC_PDLPFL_DISABLE     (0x0 << 5)
+/* the ASDM is power down */
+#define ASC_PDASDML_ENABLE     (0x1 << 7)
+#define ASC_PDASDML_DISABLE    (0x0 << 7)
+
+/* ACCELCODEC_R1F */
+/* the right channel DAC is power down */
+#define ASC_PDSCFR_ENABLE      (0x1 << 1)
+#define ASC_PDSCFR_DISABLE     (0x0 << 1)
+/* the left channel DAC is power down */
+#define ASC_PDSCFL_ENABLE      (0x1 << 2)
+#define ASC_PDSCFL_DISABLE     (0x0 << 2)
+/* the micbias is power down */
+#define ASC_PDMICB_ENABLE      (0x1 << 4)
+#define ASC_PDMICB_DISABLE     (0x0 << 4)
+/* the left channel LPF is power down */
+#define ASC_PDIB_ENABLE        (0x1 << 5)
+#define ASC_PDIB_DISABLE       (0x0 << 5)
+/* the mon mixer is power down */
+#define ASC_PDMIXM_ENABLE      (0x1 << 6)
+#define ASC_PDMIXM_DISABLE     (0x0 << 6)
+/* the mono PA is power down. */
+#define ASC_PDPAM_ENABLE       (0x1 << 7)
+#define ASC_PDPAM_DISABLE      (0x0 << 7)
+
+/* left and right PA gain */
+#define LINE_2_MIXER_GAIN      (0x5)
+#define RK1000_CODEC_NUM_REG   0x20
+
+#define        GPIO_HIGH       1
+#define        GPIO_LOW        0
 
 #endif
index f10384687ac2dbfc7ab3c241e7f2675402848394..55610210238f0227d22c743b9ab76cca40ab4eaa 100755 (executable)
@@ -10,7 +10,6 @@
  *
  *
  */
-
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/of.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
-
 #include "../codecs/rk1000_codec.h"
 #include "card_info.h"
 #include "rk_pcm.h"
 #include "rk_i2s.h"
 
-#if 1
-#define        DBG(x...)       printk(KERN_INFO x)
+#define RK1000_CARD_DBG 0
+
+#if RK1000_CARD_DBG
+#define        DBG(x...)       pr_info(x)
 #else
 #define        DBG(x...)
 #endif
 
 static int rk29_hw_params(struct snd_pcm_substream *substream,
-       struct snd_pcm_hw_params *params)
+                         struct snd_pcm_hw_params *params)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
@@ -40,22 +40,21 @@ static int rk29_hw_params(struct snd_pcm_substream *substream,
        unsigned int dai_fmt = rtd->dai_link->dai_fmt;
        int ret;
 
-       DBG("Enter::%s----%d\n", __FUNCTION__, __LINE__);
-
+       DBG("Enter::%s----%d\n",  __func__, __LINE__);
        /* set codec DAI configuration */
        ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
        if (ret < 0) {
-               printk("%s():failed to set the format for codec side\n", __FUNCTION__);
+               pr_err("%s():failed to set the format for codec side\n",
+                      __func__);
                return ret;
        }
-
        /* set cpu DAI configuration */
        ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
        if (ret < 0) {
-               printk("%s():failed to set the format for cpu side\n", __FUNCTION__);
+               pr_err("%s():failed to set the format for cpu side\n",
+                      __func__);
                return ret;
        }
-
        return 0;
 }
 
@@ -93,17 +92,14 @@ static int rockchip_rk1000_audio_probe(struct platform_device *pdev)
        struct snd_soc_card *card = &rockchip_rk1000_snd_card;
 
        card->dev = &pdev->dev;
-
        ret = rockchip_of_get_sound_card_info(card);
        if (ret) {
-               printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
+               pr_err("%s() get sound card info failed:%d\n", __func__, ret);
                return ret;
        }
-
        ret = snd_soc_register_card(card);
        if (ret)
-               printk("%s() register card failed:%d\n", __FUNCTION__, ret);
-
+               pr_err("%s() register card failed:%d\n", __func__, ret);
        return ret;
 }
 
@@ -112,7 +108,6 @@ static int rockchip_rk1000_audio_remove(struct platform_device *pdev)
        struct snd_soc_card *card = platform_get_drvdata(pdev);
 
        snd_soc_unregister_card(card);
-
        return 0;
 }