--- /dev/null
+/*
+ * drivers/input/touchscreen/gslX680.c
+ *
+ * Copyright (c) 2012 Shanghai Basewin
+ * Guan Yuwei<guanyuwei@basewin.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/async.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+#include <linux/irq.h>
+#include <mach/board.h>
+#include <linux/workqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/input/mt.h>
+
+#include "rockchip_gslX680_rk3168.h"
+
+//#define GSL_DEBUG
+//#define GSL_TIMER
+#define REPORT_DATA_ANDROID_4_0
+
+//#define HAVE_TOUCH_KEY
+
+#define GSLX680_I2C_NAME "gslX680"
+#define GSLX680_I2C_ADDR 0x40
+
+#define IRQ_PORT RK2928_PIN1_PB0
+#define WAKE_PORT RK2928_PIN0_PD3
+
+#define GSL_DATA_REG 0x80
+#define GSL_STATUS_REG 0xe0
+#define GSL_PAGE_REG 0xf0
+
+#define PRESS_MAX 255
+#define MAX_FINGERS 5
+#define MAX_CONTACTS 10
+#define DMA_TRANS_LEN 0x20
+//#define FILTER_POINT
+#ifdef FILTER_POINT
+#define FILTER_MAX 6
+#endif
+
+#define I2C_SPEED 200*1000
+
+#ifdef HAVE_TOUCH_KEY
+static u16 key = 0;
+static int key_state_flag = 0;
+struct key_data {
+ u16 key;
+ u16 x_min;
+ u16 x_max;
+ u16 y_min;
+ u16 y_max;
+};
+
+const u16 key_array[]={
+ KEY_BACK,
+ KEY_HOME,
+ KEY_MENU,
+ KEY_SEARCH,
+ };
+#define MAX_KEY_NUM (sizeof(key_array)/sizeof(key_array[0]))
+
+struct key_data gsl_key_data[MAX_KEY_NUM] = {
+ {KEY_BACK, 2048, 2048, 2048, 2048},
+ {KEY_HOME, 2048, 2048, 2048, 2048},
+ {KEY_MENU, 2048, 2048, 2048, 2048},
+ {KEY_SEARCH, 2048, 2048, 2048, 2048},
+};
+#endif
+
+struct gsl_ts_data {
+ u8 x_index;
+ u8 y_index;
+ u8 z_index;
+ u8 id_index;
+ u8 touch_index;
+ u8 data_reg;
+ u8 status_reg;
+ u8 data_size;
+ u8 touch_bytes;
+ u8 update_data;
+ u8 touch_meta_data;
+ u8 finger_size;
+};
+
+static struct gsl_ts_data devices[] = {
+ {
+ .x_index = 6,
+ .y_index = 4,
+ .z_index = 5,
+ .id_index = 7,
+ .data_reg = GSL_DATA_REG,
+ .status_reg = GSL_STATUS_REG,
+ .update_data = 0x4,
+ .touch_bytes = 4,
+ .touch_meta_data = 4,
+ .finger_size = 70,
+ },
+};
+
+struct gsl_ts {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct delayed_work work;
+ struct workqueue_struct *wq;
+ struct gsl_ts_data *dd;
+ u8 *touch_data;
+ u8 device_id;
+ u8 prev_touches;
+ bool is_suspended;
+ bool int_pending;
+ struct mutex sus_lock;
+// uint32_t gpio_irq;
+ int irq;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+#ifdef GSL_TIMER
+ struct timer_list gsl_timer;
+#endif
+ int reset_gpio; //lizhengwei
+
+};
+
+#ifdef GSL_DEBUG
+#define print_info(fmt, args...) \
+ do{ \
+ printk(fmt, ##args); \
+ }while(0)
+#else
+#define print_info(fmt, args...)
+#endif
+
+static int ts_global_reset_pin; //lizhengwei add
+
+static u32 id_sign[MAX_CONTACTS+1] = {0};
+static u8 id_state_flag[MAX_CONTACTS+1] = {0};
+static u8 id_state_old_flag[MAX_CONTACTS+1] = {0};
+static u16 x_old[MAX_CONTACTS+1] = {0};
+static u16 y_old[MAX_CONTACTS+1] = {0};
+static u16 x_new = 0;
+static u16 y_new = 0;
+#if 0
+static int gslX680_chip_init(void)
+{
+ if (WAKE_PORT > 0) {
+ gpio_free(WAKE_PORT);
+ if (gpio_request(WAKE_PORT, "gslx680 wake")) {
+ printk("pjf gpio_request(WAKE_PORT) error\n");
+ goto exit_alloc_gpio_wake_failed;
+ }
+ }
+ gpio_direction_output(WAKE_PORT, 0);
+ gpio_set_value(WAKE_PORT,GPIO_HIGH);
+
+ if (IRQ_PORT > 0) {
+ gpio_free(IRQ_PORT);
+ if (gpio_request(IRQ_PORT, "gslx680 irq")) {
+ printk("pjf gpio_request(IRQ_PORT) error\n");
+ goto exit_alloc_gpio_irg_failed;
+ }
+ }
+ gpio_pull_updown(IRQ_PORT, 1);
+
+ msleep(20);
+ return 0;
+
+exit_alloc_gpio_irg_failed:
+ gpio_free(IRQ_PORT);
+exit_alloc_gpio_wake_failed:
+ gpio_free(WAKE_PORT);
+ return -EIO;
+}
+#endif
+static int gslX680_shutdown_low(void)
+{
+ gpio_direction_output(ts_global_reset_pin, 0);
+ gpio_set_value(ts_global_reset_pin,GPIO_LOW);
+ return 0;
+}
+
+static int gslX680_shutdown_high(void)
+{
+ gpio_direction_output(ts_global_reset_pin, 0);
+ gpio_set_value(ts_global_reset_pin,GPIO_HIGH);
+ return 0;
+}
+
+static inline u16 join_bytes(u8 a, u8 b)
+{
+ u16 ab = 0;
+ ab = ab | a;
+ ab = ab << 8 | b;
+ return ab;
+}
+
+static u32 gsl_read_interface(struct i2c_client *client, u8 reg, u8 *buf, u32 num)
+{
+ struct i2c_msg xfer_msg[2];
+
+ xfer_msg[0].addr = client->addr;
+ xfer_msg[0].len = 1;
+ xfer_msg[0].flags = client->flags & I2C_M_TEN;
+ xfer_msg[0].buf = ®
+
+ xfer_msg[1].addr = client->addr;
+ xfer_msg[1].len = num;
+ xfer_msg[1].flags |= I2C_M_RD;
+ xfer_msg[1].buf = buf;
+
+ if (reg < 0x80) {
+ i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg));
+ msleep(5);
+ }
+
+ return i2c_transfer(client->adapter, xfer_msg, ARRAY_SIZE(xfer_msg)) == ARRAY_SIZE(xfer_msg) ? 0 : -EFAULT;
+}
+
+static u32 gsl_write_interface(struct i2c_client *client, const u8 reg, u8 *buf, u32 num)
+{
+ struct i2c_msg xfer_msg[1];
+
+ buf[0] = reg;
+
+ xfer_msg[0].addr = client->addr;
+ xfer_msg[0].len = num + 1;
+ xfer_msg[0].flags = client->flags & I2C_M_TEN;
+ xfer_msg[0].buf = buf;
+ xfer_msg[0].scl_rate = I2C_SPEED;
+
+ return i2c_transfer(client->adapter, xfer_msg, 1) == 1 ? 0 : -EFAULT;
+}
+
+static int gsl_ts_write(struct i2c_client *client, u8 addr, u8 *pdata, int datalen)
+{
+ int ret = 0;
+ u8 tmp_buf[128];
+ unsigned int bytelen = 0;
+ if (datalen > 125)
+ {
+ printk("%s too big datalen = %d!\n", __func__, datalen);
+ return -1;
+ }
+
+ tmp_buf[0] = addr;
+ bytelen++;
+
+ if (datalen != 0 && pdata != NULL)
+ {
+ memcpy(&tmp_buf[bytelen], pdata, datalen);
+ bytelen += datalen;
+ }
+
+ ret = i2c_master_send(client, tmp_buf, bytelen);
+ return ret;
+}
+
+static int gsl_ts_read(struct i2c_client *client, u8 addr, u8 *pdata, unsigned int datalen)
+{
+ int ret = 0;
+
+ if (datalen > 126)
+ {
+ printk("%s too big datalen = %d!\n", __func__, datalen);
+ return -1;
+ }
+
+ ret = gsl_ts_write(client, addr, NULL, 0);
+ if (ret < 0)
+ {
+ printk("%s set data address fail!\n", __func__);
+ return ret;
+ }
+
+ return i2c_master_recv(client, pdata, datalen);
+}
+
+
+static __inline__ void fw2buf(u8 *buf, const u32 *fw)
+{
+ u32 *u32_buf = (int *)buf;
+ *u32_buf = *fw;
+}
+
+static void gsl_load_fw(struct i2c_client *client)
+{
+ u8 buf[DMA_TRANS_LEN*4 + 1] = {0};
+ u8 send_flag = 1;
+ u8 *cur = buf + 1;
+ u32 source_line = 0;
+ u32 source_len;
+ u8 read_buf[4] = {0};
+ struct fw_data *ptr_fw;
+
+ printk("=============gsl_load_fw start==============\n");
+
+#ifdef GSL1680E_COMPATIBLE
+ msleep(50);
+ gsl_ts_read(client, 0xfc, read_buf, 4);
+ //printk("read 0xfc = %x %x %x %x\n", read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+
+ if(read_buf[2] != 0x82 && read_buf[2] != 0x88)
+ {
+ msleep(100);
+ gsl_ts_read(client, 0xfc, read_buf, 4);
+ //printk("read 0xfc = %x %x %x %x\n", read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+ }
+
+ if(read_buf[2] == 0x82)
+ {
+ ptr_fw = GSL1680E_FW;
+ source_len = ARRAY_SIZE(GSL1680E_FW);
+ }
+ else
+#endif
+ {
+ ptr_fw = GSLX680_FW;
+ source_len = ARRAY_SIZE(GSLX680_FW);
+ }
+
+ for (source_line = 0; source_line < source_len; source_line++)
+ {
+ /* init page trans, set the page val */
+ if (GSL_PAGE_REG == ptr_fw[source_line].offset)
+ {
+ fw2buf(cur, &ptr_fw[source_line].val);
+ gsl_write_interface(client, GSL_PAGE_REG, buf, 4);
+ send_flag = 1;
+ }
+ else
+ {
+ if (1 == send_flag % (DMA_TRANS_LEN < 0x20 ? DMA_TRANS_LEN : 0x20))
+ buf[0] = (u8)ptr_fw[source_line].offset;
+
+ fw2buf(cur, &ptr_fw[source_line].val);
+ cur += 4;
+
+ if (0 == send_flag % (DMA_TRANS_LEN < 0x20 ? DMA_TRANS_LEN : 0x20))
+ {
+ gsl_write_interface(client, buf[0], buf, cur - buf - 1);
+ cur = buf + 1;
+ }
+
+ send_flag++;
+ }
+ }
+
+ printk("=============gsl_load_fw end==============\n");
+
+}
+
+
+static void test_i2c(struct i2c_client *client)
+{
+ u8 read_buf = 0;
+ u8 write_buf = 0x12;
+ int ret;
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if (ret < 0)
+ {
+ pr_info("I2C transfer error!\n");
+ }
+ else
+ {
+ pr_info("I read reg 0xf0 is %x\n", read_buf);
+ }
+ msleep(10);
+
+ ret = gsl_ts_write(client, 0xf0, &write_buf, sizeof(write_buf));
+ if (ret < 0)
+ {
+ pr_info("I2C transfer error!\n");
+ }
+ else
+ {
+ pr_info("I write reg 0xf0 0x12\n");
+ }
+ msleep(10);
+
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if (ret < 0 )
+ {
+ pr_info("I2C transfer error!\n");
+ }
+ else
+ {
+ pr_info("I read reg 0xf0 is 0x%x\n", read_buf);
+ }
+ msleep(10);
+
+}
+
+
+static void startup_chip(struct i2c_client *client)
+{
+ u8 tmp = 0x00;
+ gsl_ts_write(client, 0xe0, &tmp, 1);
+ msleep(10);
+}
+
+static void reset_chip(struct i2c_client *client)
+{
+ u8 buf[4] = {0x00};
+ u8 tmp = 0x88;
+ gsl_ts_write(client, 0xe0, &tmp, sizeof(tmp));
+ msleep(10);
+
+ tmp = 0x04;
+ gsl_ts_write(client, 0xe4, &tmp, sizeof(tmp));
+ msleep(10);
+
+ gsl_ts_write(client, 0xbc, buf, sizeof(buf));
+ msleep(10);
+}
+
+static void init_chip(struct i2c_client *client)
+{
+ gslX680_shutdown_low();
+ msleep(50);
+ gslX680_shutdown_high();
+ msleep(30);
+ reset_chip(client);
+ gsl_load_fw(client);
+ startup_chip(client);
+ reset_chip(client);
+ startup_chip(client);
+}
+
+static void check_mem_data(struct i2c_client *client)
+{
+ char write_buf;
+ char read_buf[4] = {0};
+
+ msleep(30);
+ write_buf = 0x00;
+ gsl_ts_write(client,0xf0, &write_buf, sizeof(write_buf));
+ gsl_ts_read(client,0x00, read_buf, sizeof(read_buf));
+ gsl_ts_read(client,0x00, read_buf, sizeof(read_buf));
+ if (read_buf[3] != 0x1 || read_buf[2] != 0 || read_buf[1] != 0 || read_buf[0] != 0)
+ {
+ printk("!!!!!!!!!!!page: %x offset: %x val: %x %x %x %x\n",0x0, 0x0, read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+ init_chip(client);
+ }
+}
+
+#ifdef FILTER_POINT
+static void filter_point(u16 x, u16 y , u8 id)
+{
+ u16 x_err =0;
+ u16 y_err =0;
+ u16 filter_step_x = 0, filter_step_y = 0;
+
+ id_sign[id] = id_sign[id] + 1;
+ if(id_sign[id] == 1)
+ {
+ x_old[id] = x;
+ y_old[id] = y;
+ }
+
+ x_err = x > x_old[id] ? (x -x_old[id]) : (x_old[id] - x);
+ y_err = y > y_old[id] ? (y -y_old[id]) : (y_old[id] - y);
+
+ if( (x_err > FILTER_MAX && y_err > FILTER_MAX/3) || (x_err > FILTER_MAX/3 && y_err > FILTER_MAX) )
+ {
+ filter_step_x = x_err;
+ filter_step_y = y_err;
+ }
+ else
+ {
+ if(x_err > FILTER_MAX)
+ filter_step_x = x_err;
+ if(y_err> FILTER_MAX)
+ filter_step_y = y_err;
+ }
+
+ if(x_err <= 2*FILTER_MAX && y_err <= 2*FILTER_MAX)
+ {
+ filter_step_x >>= 2;
+ filter_step_y >>= 2;
+ }
+ else if(x_err <= 3*FILTER_MAX && y_err <= 3*FILTER_MAX)
+ {
+ filter_step_x >>= 1;
+ filter_step_y >>= 1;
+ }
+
+ x_new = x > x_old[id] ? (x_old[id] + filter_step_x) : (x_old[id] - filter_step_x);
+ y_new = y > y_old[id] ? (y_old[id] + filter_step_y) : (y_old[id] - filter_step_y);
+
+ x_old[id] = x_new;
+ y_old[id] = y_new;
+}
+#else
+
+static void record_point(u16 x, u16 y , u8 id)
+{
+ u16 x_err =0;
+ u16 y_err =0;
+
+ id_sign[id]=id_sign[id]+1;
+
+ if(id_sign[id]==1){
+ x_old[id]=x;
+ y_old[id]=y;
+ }
+
+ x = (x_old[id] + x)/2;
+ y = (y_old[id] + y)/2;
+
+ if(x>x_old[id]){
+ x_err=x -x_old[id];
+ }
+ else{
+ x_err=x_old[id]-x;
+ }
+
+ if(y>y_old[id]){
+ y_err=y -y_old[id];
+ }
+ else{
+ y_err=y_old[id]-y;
+ }
+
+ if( (x_err > 3 && y_err > 1) || (x_err > 1 && y_err > 3) ){
+ x_new = x; x_old[id] = x;
+ y_new = y; y_old[id] = y;
+ }
+ else{
+ if(x_err > 3){
+ x_new = x; x_old[id] = x;
+ }
+ else
+ x_new = x_old[id];
+ if(y_err> 3){
+ y_new = y; y_old[id] = y;
+ }
+ else
+ y_new = y_old[id];
+ }
+
+ if(id_sign[id]==1){
+ x_new= x_old[id];
+ y_new= y_old[id];
+ }
+
+}
+#endif
+
+#ifdef HAVE_TOUCH_KEY
+static void report_key(struct gsl_ts *ts, u16 x, u16 y)
+{
+ u16 i = 0;
+
+ for(i = 0; i < MAX_KEY_NUM; i++)
+ {
+ if((gsl_key_data[i].x_min < x) && (x < gsl_key_data[i].x_max)&&(gsl_key_data[i].y_min < y) && (y < gsl_key_data[i].y_max))
+ {
+ key = gsl_key_data[i].key;
+ input_report_key(ts->input, key, 1);
+ input_sync(ts->input);
+ key_state_flag = 1;
+ break;
+ }
+ }
+}
+#endif
+
+static void report_data(struct gsl_ts *ts, u16 x, u16 y, u8 pressure, u8 id)
+{
+ swap(x, y);
+
+ print_info("#####id=%d,x=%d,y=%d######\n",id,x,y);
+
+ if(x>=SCREEN_MAX_X||y>=SCREEN_MAX_Y)
+ {
+ #ifdef HAVE_TOUCH_KEY
+ report_key(ts,x,y);
+ #endif
+ return;
+ }
+
+#ifdef REPORT_DATA_ANDROID_4_0
+ input_mt_slot(ts->input, id);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
+ input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pressure);
+ input_report_abs(ts->input, ABS_MT_POSITION_X, x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
+ input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 1);
+#else
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
+ input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, pressure);
+ input_report_abs(ts->input, ABS_MT_POSITION_X,x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
+ input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, 1);
+ input_mt_sync(ts->input);
+#endif
+}
+
+static void process_gslX680_data(struct gsl_ts *ts)
+{
+ u8 id, touches;
+ u16 x, y;
+ int i = 0;
+
+ touches = ts->touch_data[ts->dd->touch_index];
+ for(i=1;i<=MAX_CONTACTS;i++)
+ {
+ if(touches == 0)
+ id_sign[i] = 0;
+ id_state_flag[i] = 0;
+ }
+ for(i= 0;i < (touches > MAX_FINGERS ? MAX_FINGERS : touches);i ++)
+ {
+ x = join_bytes( ( ts->touch_data[ts->dd->x_index + 4 * i + 1] & 0xf),
+ ts->touch_data[ts->dd->x_index + 4 * i]);
+ y = join_bytes(ts->touch_data[ts->dd->y_index + 4 * i + 1],
+ ts->touch_data[ts->dd->y_index + 4 * i ]);
+ id = ts->touch_data[ts->dd->id_index + 4 * i] >> 4;
+
+ if(1 <=id && id <= MAX_CONTACTS)
+ {
+ #ifdef FILTER_POINT
+ filter_point(x, y ,id);
+ #else
+ record_point(x, y , id);
+ #endif
+ report_data(ts, x_new, y_new, 50, id);
+ id_state_flag[id] = 1;
+ }
+ }
+ for(i=1;i<=MAX_CONTACTS;i++)
+ {
+ if( (0 == touches) || ((0 != id_state_old_flag[i]) && (0 == id_state_flag[i])) )
+ {
+ #ifdef REPORT_DATA_ANDROID_4_0
+ input_mt_slot(ts->input, i);
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, -1);
+ input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, false);
+ #endif
+ id_sign[i]=0;
+ }
+ id_state_old_flag[i] = id_state_flag[i];
+ }
+#ifndef REPORT_DATA_ANDROID_4_0
+ if(0 == touches)
+ {
+ input_mt_sync(ts->input);
+ #ifdef HAVE_TOUCH_KEY
+ if(key_state_flag)
+ {
+ input_report_key(ts->input, key, 0);
+ input_sync(ts->input);
+ key_state_flag = 0;
+ }
+ #endif
+ }
+#endif
+ input_sync(ts->input);
+ ts->prev_touches = touches;
+}
+
+
+static void gsl_ts_xy_worker(struct work_struct *work)
+{
+ int rc;
+ u8 read_buf[4] = {0};
+
+ struct gsl_ts *ts = container_of(work, struct gsl_ts,work);
+
+ print_info("---gsl_ts_xy_worker---\n");
+
+ /* read data from DATA_REG */
+ rc = gsl_ts_read(ts->client, 0x80, ts->touch_data, ts->dd->data_size);
+ print_info("---touches: %d ---\n",ts->touch_data[0]);
+
+ if (rc < 0)
+ {
+ dev_err(&ts->client->dev, "read failed\n");
+ goto schedule;
+ }
+
+ if (ts->touch_data[ts->dd->touch_index] == 0xff) {
+ goto schedule;
+ }
+
+ rc = gsl_ts_read( ts->client, 0xbc, read_buf, sizeof(read_buf));
+ if (rc < 0)
+ {
+ dev_err(&ts->client->dev, "read 0xbc failed\n");
+ goto schedule;
+ }
+ print_info("//////// reg %x : %x %x %x %x\n",0xbc, read_buf[3], read_buf[2], read_buf[1], read_buf[0]);
+
+ if (read_buf[3] == 0 && read_buf[2] == 0 && read_buf[1] == 0 && read_buf[0] == 0)
+ {
+ process_gslX680_data(ts);
+ }
+ else
+ {
+ reset_chip(ts->client);
+ startup_chip(ts->client);
+ }
+
+schedule:
+ enable_irq(ts->irq);
+
+}
+
+static irqreturn_t gsl_ts_irq(int irq, void *dev_id)
+{
+ struct gsl_ts *ts = dev_id;
+
+ print_info("==========GSLX680 Interrupt============\n");
+
+ disable_irq_nosync(ts->irq);
+
+// if (!work_pending(&ts->work))
+ {
+ queue_delayed_work(ts->wq, &ts->work,msecs_to_jiffies(10));
+ }
+
+ return IRQ_HANDLED;
+
+}
+
+#ifdef GSL_TIMER
+static void gsl_timer_handle(unsigned long data)
+{
+ struct gsl_ts *ts = (struct gsl_ts *)data;
+
+#ifdef GSL_DEBUG
+ printk("----------------gsl_timer_handle-----------------\n");
+#endif
+
+ disable_irq_nosync(ts->irq);
+ check_mem_data(ts->client);
+ ts->gsl_timer.expires = jiffies + 3 * HZ;
+ add_timer(&ts->gsl_timer);
+ enable_irq(ts->irq);
+
+}
+#endif
+
+static int gsl_ts_init_ts(struct i2c_client *client, struct gsl_ts *ts)
+{
+ struct input_dev *input_device;
+ int i, rc = 0;
+
+ printk("[GSLX680] Enter %s\n", __func__);
+
+
+ ts->dd = &devices[ts->device_id];
+
+ if (ts->device_id == 0) {
+ ts->dd->data_size = MAX_FINGERS * ts->dd->touch_bytes + ts->dd->touch_meta_data;
+ ts->dd->touch_index = 0;
+ }
+
+ ts->touch_data = kzalloc(ts->dd->data_size, GFP_KERNEL);
+ if (!ts->touch_data) {
+ pr_err("%s: Unable to allocate memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ts->prev_touches = 0;
+
+ input_device = input_allocate_device();
+ if (!input_device) {
+ rc = -ENOMEM;
+ goto error_alloc_dev;
+ }
+
+ ts->input = input_device;
+ input_device->name = GSLX680_I2C_NAME;
+ input_device->id.bustype = BUS_I2C;
+ input_device->dev.parent = &client->dev;
+ input_set_drvdata(input_device, ts);
+
+#ifdef REPORT_DATA_ANDROID_4_0
+ __set_bit(EV_ABS, input_device->evbit);
+ __set_bit(EV_KEY, input_device->evbit);
+ __set_bit(EV_REP, input_device->evbit);
+ __set_bit(INPUT_PROP_DIRECT, input_device->propbit);
+ input_mt_init_slots(input_device, (MAX_CONTACTS+1));
+#else
+ input_set_abs_params(input_device,ABS_MT_TRACKING_ID, 0, (MAX_CONTACTS+1), 0, 0);
+ set_bit(EV_ABS, input_device->evbit);
+ set_bit(EV_KEY, input_device->evbit);
+#endif
+
+#ifdef HAVE_TOUCH_KEY
+ input_device->evbit[0] = BIT_MASK(EV_KEY);
+ //input_device->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ for (i = 0; i < MAX_KEY_NUM; i++)
+ set_bit(key_array[i], input_device->keybit);
+#endif
+
+ set_bit(ABS_MT_POSITION_X, input_device->absbit);
+ set_bit(ABS_MT_POSITION_Y, input_device->absbit);
+ set_bit(ABS_MT_TOUCH_MAJOR, input_device->absbit);
+ set_bit(ABS_MT_WIDTH_MAJOR, input_device->absbit);
+
+ input_set_abs_params(input_device,ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
+ input_set_abs_params(input_device,ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
+ input_set_abs_params(input_device,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);
+ input_set_abs_params(input_device,ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
+
+ client->irq = ts->irq; //IRQ_PORT,
+ //ts->irq = client->irq;
+
+ ts->wq = create_singlethread_workqueue("kworkqueue_ts");
+ if (!ts->wq) {
+ dev_err(&client->dev, "Could not create workqueue\n");
+ goto error_wq_create;
+ }
+ flush_workqueue(ts->wq);
+
+ INIT_DELAYED_WORK(&ts->work, gsl_ts_xy_worker);
+
+ rc = input_register_device(input_device);
+ if (rc)
+ goto error_unreg_device;
+
+ return 0;
+
+error_unreg_device:
+ destroy_workqueue(ts->wq);
+error_wq_create:
+ input_free_device(input_device);
+error_alloc_dev:
+ kfree(ts->touch_data);
+ return rc;
+}
+
+static int gsl_ts_suspend(struct device *dev)
+{
+ struct gsl_ts *ts = dev_get_drvdata(dev);
+ int rc = 0;
+
+ printk("I'am in gsl_ts_suspend() start\n");
+
+#ifdef GSL_TIMER
+ printk( "gsl_ts_suspend () : delete gsl_timer\n");
+
+ del_timer(&ts->gsl_timer);
+#endif
+ disable_irq_nosync(ts->irq);
+
+ gslX680_shutdown_low();
+
+ return 0;
+}
+
+static int gsl_ts_resume(struct device *dev)
+{
+ struct gsl_ts *ts = dev_get_drvdata(dev);
+ int rc = 0;
+
+ printk("I'am in gsl_ts_resume() start\n");
+
+ gslX680_shutdown_low();
+ msleep(50);
+ gslX680_shutdown_high();
+ msleep(30);
+ reset_chip(ts->client);
+ startup_chip(ts->client);
+ check_mem_data(ts->client);
+
+#ifdef GSL_TIMER
+ printk( "gsl_ts_resume () : add gsl_timer\n");
+
+ init_timer(&ts->gsl_timer);
+ ts->gsl_timer.expires = jiffies + 3 * HZ;
+ ts->gsl_timer.function = &gsl_timer_handle;
+ ts->gsl_timer.data = (unsigned long)ts;
+ add_timer(&ts->gsl_timer);
+#endif
+
+ enable_irq(ts->irq);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void gsl_ts_early_suspend(struct early_suspend *h)
+{
+ struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
+ printk("[GSL1680] Enter %s\n", __func__);
+ gsl_ts_suspend(&ts->client->dev);
+}
+
+static void gsl_ts_late_resume(struct early_suspend *h)
+{
+ struct gsl_ts *ts = container_of(h, struct gsl_ts, early_suspend);
+ printk("[GSL1680] Enter %s\n", __func__);
+ gsl_ts_resume(&ts->client->dev);
+}
+#endif
+
+static int __devinit gsl_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ts_hw_data *pdata = client->dev.platform_data;
+
+ struct gsl_ts *ts;
+ int rc;
+
+ printk("GSLX680 Enter %s\n", __func__);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C functionality not supported\n");
+ return -ENODEV;
+ }
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+ printk("==kzalloc success=\n");
+
+ ts->client = client;
+ ts->device_id = id->driver_data;
+
+ ts->is_suspended = false;
+ ts->int_pending = false;
+ ts->reset_gpio = pdata->reset_gpio; //lizhengwei
+ ts->irq= gpio_to_irq(pdata->touch_en_gpio); //lizhengwei
+ mutex_init(&ts->sus_lock);
+
+ts_global_reset_pin=ts->reset_gpio;
+
+ i2c_set_clientdata(client, ts);
+
+ if (pdata->init_platform_hw)
+ pdata->init_platform_hw();
+
+ rc = gsl_ts_init_ts(client, ts);
+ if (rc < 0) {
+ dev_err(&client->dev, "GSLX680 init failed\n");
+ goto error_mutex_destroy;
+ }
+
+ rc= request_irq(client->irq, gsl_ts_irq, IRQF_TRIGGER_RISING, client->name, ts);
+ if (rc < 0) {
+ printk( "gsl_probe: request irq failed\n");
+ goto error_req_irq_fail;
+ }
+
+ //lizhengwei add
+ if(1)
+ {
+ u8 read_buf = 0;
+ int ret;
+ ret = gsl_ts_read( client, 0xf0, &read_buf, sizeof(read_buf) );
+ if (ret < 0)
+ {
+ pr_info("gslx680 I2C transfer error!\n");
+ goto error_req_irq_fail;
+ }
+ }
+
+
+ //gslX680_chip_init();
+ init_chip(ts->client);
+ check_mem_data(ts->client);
+
+
+#ifdef GSL_TIMER
+ printk( "gsl_ts_probe () : add gsl_timer\n");
+
+ init_timer(&ts->gsl_timer);
+ ts->gsl_timer.expires = jiffies + 3 * HZ; //¶¨Ê±3 ÃëÖÓ
+ ts->gsl_timer.function = &gsl_timer_handle;
+ ts->gsl_timer.data = (unsigned long)ts;
+ add_timer(&ts->gsl_timer);
+#endif
+
+ /* create debug attribute */
+ //rc = device_create_file(&ts->input->dev, &dev_attr_debug_enable);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->early_suspend.suspend = gsl_ts_early_suspend;
+ ts->early_suspend.resume = gsl_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ printk("[GSLX680] End %s\n", __func__);
+
+ return 0;
+
+//exit_set_irq_mode:
+error_req_irq_fail:
+ free_irq(ts->irq, ts);
+
+error_mutex_destroy:
+ mutex_destroy(&ts->sus_lock);
+ input_free_device(ts->input);
+ kfree(ts);
+ return rc;
+}
+
+static int __devexit gsl_ts_remove(struct i2c_client *client)
+{
+ struct gsl_ts *ts = i2c_get_clientdata(client);
+ printk("==gsl_ts_remove=\n");
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif
+
+ device_init_wakeup(&client->dev, 0);
+ cancel_delayed_work_sync(&ts->work);
+ free_irq(ts->irq, ts);
+ destroy_workqueue(ts->wq);
+ input_unregister_device(ts->input);
+ mutex_destroy(&ts->sus_lock);
+
+ //device_remove_file(&ts->input->dev, &dev_attr_debug_enable);
+
+ kfree(ts->touch_data);
+ kfree(ts);
+
+ return 0;
+}
+
+static const struct i2c_device_id gsl_ts_id[] = {
+ {GSLX680_I2C_NAME, 0},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, gsl_ts_id);
+
+
+static struct i2c_driver gsl_ts_driver = {
+ .driver = {
+ .name = GSLX680_I2C_NAME,
+ .owner = THIS_MODULE,
+ },
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = gsl_ts_suspend,
+ .resume = gsl_ts_resume,
+#endif
+ .probe = gsl_ts_probe,
+ .remove = __devexit_p(gsl_ts_remove),
+ .id_table = gsl_ts_id,
+};
+
+static int __init gsl_ts_init(void)
+{
+ int ret;
+ printk("==gsl_ts_init==\n");
+ ret = i2c_add_driver(&gsl_ts_driver);
+ printk("ret=%d\n",ret);
+ return ret;
+}
+static void __exit gsl_ts_exit(void)
+{
+ printk("==gsl_ts_exit==\n");
+ i2c_del_driver(&gsl_ts_driver);
+ return;
+}
+
+module_init(gsl_ts_init);
+module_exit(gsl_ts_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GSLX680 touchscreen controller driver");
+MODULE_AUTHOR("Guan Yuwei, guanyuwei@basewin.com");
+MODULE_ALIAS("platform:gsl_ts");
#include <linux/proc_fs.h>
#include <linux/gpio.h>
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
#if 0
#define DBG(x...) printk(KERN_INFO x)
#else
#endif
#define alsa_dbg DBG
+static int set_spk = 1; // add by xhc when insert hdmi 0, no insert hdmi 1
#define RT5633_SPK_TIMER 0 //if enable this, MUST enable RT5633_EQ_FUNC_ENA and RT5633_EQ_FUNC_SEL==RT5633_EQ_FOR_MANUAL first!
#if (RT5633_SPK_TIMER == 1)
static struct timer_list spk_timer;
#undef SPK_CTL
// #undef SPK_CON
#define SPK_CON RK30_PIN2_PD7 //RK30_PIN4_PC5
-
+#define HP_DET RK30_PIN0_PB5
+static int HP_IRQ=0;
+static int hp_irq_flag = 0;
//#define SPK_CTL RK29_PIN6_PB6
//#define EAR_CON_PIN RK29_PIN6_PB5
#undef EAR_CON_PIN
#define es8323_DEF_VOL 0x1e
#endif
-static int es8323_set_bias_level(struct snd_soc_codec *codec,
- enum snd_soc_bias_level level);
+static int es8323_set_bias_level(struct snd_soc_codec *codec,enum snd_soc_bias_level level);
+extern int es8323_dapm_pre_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event);
+extern int es8323_dapm_post_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event);
/*
* es8323 register cache
* We can't read the es8323 register space when we
int is_biason;
};
+static void hp_detect_do_switch(struct work_struct *work)
+{
+ int ret;
+ int irq = gpio_to_irq(HP_DET);
+ unsigned int type;
+
+ //rk28_send_wakeup_key();
+ printk("hjc:%s,irq=%d\n",__func__,irq);
+ type = gpio_get_value(HP_DET) ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+ ret = irq_set_irq_type(irq, type);
+ if (ret < 0) {
+ pr_err("%s: irq_set_irq_type(%d, %d) failed\n", __func__, irq, type);
+ }
+
+ hp_irq_flag = 1;
+
+ if(0 == gpio_get_value(HP_DET)){
+ printk("hp_det = 0,insert hp\n");
+ gpio_set_value(SPK_CON,0);
+ }else if(1 == gpio_get_value(HP_DET)){
+ printk("hp_det = 1,deinsert hp\n");
+ gpio_set_value(SPK_CON,1);
+ }
+ enable_irq(irq);
+}
+
+
+static DECLARE_DELAYED_WORK(wakeup_work, hp_detect_do_switch);
+
+
+static irqreturn_t hp_det_irq_handler(int irq, void *dev_id)
+{
+#if 0
+ printk("%s=%d,%d\n",__FUNCTION__,HP_IRQ,HP_DET);
+ //disable_irq_nosync(ts->client->irq);
+ //queue_work(gt801_wq, &ts->work);
+ if(0 == gpio_get_value(HP_DET)){
+ printk("hp_det = 0,insert hp\n");
+ gpio_set_value(SPK_CON,0);
+ }else if(1 == gpio_get_value(HP_DET)){
+ printk("hp_det = 1,insert hp\n");
+ gpio_set_value(SPK_CON,1);
+ }
+ return IRQ_HANDLED;
+#endif
+ printk("hjc:%s>>>>\n",__func__);
+ disable_irq_nosync(irq); // for irq debounce
+ //wake_lock_timeout(&usb_wakelock, WAKE_LOCK_TIMEOUT);
+ schedule_delayed_work(&wakeup_work, HZ / 10);
+ return IRQ_HANDLED;
+
+}
+
+
+
static unsigned int es8323_read_reg_cache(struct snd_soc_codec *codec,
unsigned int reg)
{
- u16 *cache = codec->reg_cache;
+ //u16 *cache = codec->reg_cache;
if (reg >= ARRAY_SIZE(es8323_reg))
return -1;
return es8323_reg[reg];
static int es8323_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
- u16 *cache = codec->reg_cache;
+ //u16 *cache = codec->reg_cache;
u8 data[2];
int ret;
snd_soc_write(codec, ES8323_CONTROL1, 0x80);
return snd_soc_write(codec, ES8323_CONTROL1, 0x00);
}
-static int es8323_volatile_register(
- struct snd_soc_codec *codec, unsigned int reg)
-{
- if(reg<0x35)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-static int es8323_readable_register(
- struct snd_soc_codec *codec, unsigned int reg)
-{
- if(reg<0x35)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-/*
- * es8323 Controls
- */
-/*
-static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
-static const struct soc_enum bass_boost =
- SOC_ENUM_SINGLE(es8323_BASS, 7, 2, bass_boost_txt);
-
-static const char *bass_filter_txt[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
-static const struct soc_enum bass_filter =
- SOC_ENUM_SINGLE(es8323_BASS, 6, 2, bass_filter_txt);
-
-static const char *treble_txt[] = {"8kHz", "4kHz"};
-static const struct soc_enum treble =
- SOC_ENUM_SINGLE(es8323_TREBLE, 6, 2, treble_txt);
-
-static const char *stereo_3d_lc_txt[] = {"200Hz", "500Hz"};
-static const struct soc_enum stereo_3d_lc =
- SOC_ENUM_SINGLE(es8323_3D, 5, 2, stereo_3d_lc_txt);
-
-static const char *stereo_3d_uc_txt[] = {"2.2kHz", "1.5kHz"};
-static const struct soc_enum stereo_3d_uc =
- SOC_ENUM_SINGLE(es8323_3D, 6, 2, stereo_3d_uc_txt);
-
-static const char *stereo_3d_func_txt[] = {"Capture", "Playback"};
-static const struct soc_enum stereo_3d_func =
- SOC_ENUM_SINGLE(es8323_3D, 7, 2, stereo_3d_func_txt);
-*/
+static const char *es8323_line_texts[] = {
+ "Line 1", "Line 2", "PGA"};
+
+static const unsigned int es8323_line_values[] = {
+ 0, 1, 3};
+static const char *es8323_pga_sel[] = {"Line 1", "Line 2", "Differential"};
static const char *stereo_3d_txt[] = {"No 3D ", "Level 1","Level 2","Level 3","Level 4","Level 5","Level 6","Level 7"};
-static const struct soc_enum stereo_3d =
- SOC_ENUM_SINGLE(ES8323_DACCONTROL7, 2, 8, stereo_3d_txt);
-
static const char *alc_func_txt[] = {"Off", "Right", "Left", "Stereo"};
-static const struct soc_enum alc_func =
- SOC_ENUM_SINGLE(ES8323_ADCCONTROL10, 6, 4, alc_func_txt);
-
-static const char *ng_type_txt[] = {"Constant PGA Gain",
- "Mute ADC Output"};
-static const struct soc_enum ng_type =
- SOC_ENUM_SINGLE(ES8323_ADCCONTROL14, 1, 2, ng_type_txt);
-
+static const char *ng_type_txt[] = {"Constant PGA Gain","Mute ADC Output"};
static const char *deemph_txt[] = {"None", "32Khz", "44.1Khz", "48Khz"};
-static const struct soc_enum deemph =
- SOC_ENUM_SINGLE(ES8323_DACCONTROL6, 6, 4, deemph_txt);
-
-static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert",
- "L + R Invert"};
-static const struct soc_enum adcpol =
- SOC_ENUM_SINGLE(ES8323_ADCCONTROL6, 6, 4, adcpol_txt);
+static const char *adcpol_txt[] = {"Normal", "L Invert", "R Invert","L + R Invert"};
+static const char *es8323_mono_mux[] = {"Stereo", "Mono (Left)","Mono (Right)"};
+static const char *es8323_diff_sel[] = {"Line 1", "Line 2"};
+
+static const struct soc_enum es8323_enum[]={
+ SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 3, 7, ARRAY_SIZE(es8323_line_texts), es8323_line_texts, es8323_line_values),/* LLINE */
+ SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 0, 7, ARRAY_SIZE(es8323_line_texts), es8323_line_texts, es8323_line_values),/* rline */
+ SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 6, 3, ARRAY_SIZE(es8323_pga_sel), es8323_line_texts, es8323_line_values),/* Left PGA Mux */
+ SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 4, 3, ARRAY_SIZE(es8323_pga_sel), es8323_line_texts, es8323_line_values),/* Right PGA Mux */
+ SOC_ENUM_SINGLE(ES8323_DACCONTROL7, 2, 8, stereo_3d_txt),/* stereo-3d */
+ SOC_ENUM_SINGLE(ES8323_ADCCONTROL10, 6, 4, alc_func_txt),/*alc func*/
+ SOC_ENUM_SINGLE(ES8323_ADCCONTROL14, 1, 2, ng_type_txt),/*noise gate type*/
+ SOC_ENUM_SINGLE(ES8323_DACCONTROL6, 6, 4, deemph_txt),/*Playback De-emphasis*/
+ SOC_ENUM_SINGLE(ES8323_ADCCONTROL6, 6, 4, adcpol_txt),
+ SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 3, 3, es8323_mono_mux),
+ SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 7, 2, es8323_diff_sel),
+ };
+
static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
static const DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 50, 1);
static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const struct snd_kcontrol_new es8323_snd_controls[] = {
-/*
-SOC_ENUM("Bass Boost", bass_boost),
-SOC_ENUM("Bass Filter", bass_filter),
-SOC_SINGLE("Bass Volume", es8323_BASS, 0, 15, 1),
-
-SOC_SINGLE("Treble Volume", es8323_TREBLE, 0, 15, 0),
-SOC_ENUM("Treble Cut-off", treble),
-
-SOC_SINGLE("3D Switch", es8323_3D, 0, 1, 0),
-SOC_SINGLE("3D Volume", es8323_3D, 1, 15, 0),
-SOC_ENUM("3D Lower Cut-off", stereo_3d_lc),
-SOC_ENUM("3D Upper Cut-off", stereo_3d_uc),
-SOC_ENUM("3D Mode", stereo_3d_func),
-*/
-SOC_ENUM("3D Mode", stereo_3d),
+SOC_ENUM("3D Mode", es8323_enum[4]),
SOC_SINGLE("ALC Capture Target Volume", ES8323_ADCCONTROL11, 4, 15, 0),
SOC_SINGLE("ALC Capture Max PGA", ES8323_ADCCONTROL10, 3, 7, 0),
SOC_SINGLE("ALC Capture Min PGA", ES8323_ADCCONTROL10, 0, 7, 0),
-SOC_ENUM("ALC Capture Function", alc_func),
+SOC_ENUM("ALC Capture Function", es8323_enum[5]),
SOC_SINGLE("ALC Capture ZC Switch", ES8323_ADCCONTROL13, 6, 1, 0),
SOC_SINGLE("ALC Capture Hold Time", ES8323_ADCCONTROL11, 0, 15, 0),
SOC_SINGLE("ALC Capture Decay Time", ES8323_ADCCONTROL12, 4, 15, 0),
SOC_SINGLE("ALC Capture Attack Time", ES8323_ADCCONTROL12, 0, 15, 0),
SOC_SINGLE("ALC Capture NG Threshold", ES8323_ADCCONTROL14, 3, 31, 0),
-SOC_ENUM("ALC Capture NG Type", ng_type),
+SOC_ENUM("ALC Capture NG Type",es8323_enum[6]),
SOC_SINGLE("ALC Capture NG Switch", ES8323_ADCCONTROL14, 0, 1, 0),
-
SOC_SINGLE("ZC Timeout Switch", ES8323_ADCCONTROL13, 6, 1, 0),
-
-SOC_DOUBLE_R_TLV("Capture Digital Volume", ES8323_ADCCONTROL8, ES8323_ADCCONTROL9,
- 0, 255, 1, adc_tlv),
-
-SOC_SINGLE("Capture Mute", ES8323_ADCCONTROL7, 2, 1, 0),
- /*
-SOC_DOUBLE_R_TLV("Capture Volume", es8323_LINVOL, es8323_RINVOL,
- 0, 63, 0, pga_tlv),
- */
+SOC_DOUBLE_R_TLV("Capture Digital Volume", ES8323_ADCCONTROL8, ES8323_ADCCONTROL9,0, 255, 1, adc_tlv),
+SOC_SINGLE("Capture Mute", ES8323_ADCCONTROL7, 2, 1, 0),
SOC_SINGLE_TLV("Left Channel Capture Volume", ES8323_ADCCONTROL1, 4, 15, 0, bypass_tlv),
SOC_SINGLE_TLV("Right Channel Capture Volume", ES8323_ADCCONTROL1, 0, 15, 0, bypass_tlv),
-
-//SOC_DOUBLE_R("Capture ZC Switch", es8323_LINVOL, es8323_RINVOL, 6, 1, 0),
-//SOC_SINGLE("Capture Switch", ES8323_ADCPOWER, 4, 3, 1),
-
-SOC_ENUM("Playback De-emphasis", deemph),
-
-SOC_ENUM("Capture Polarity", adcpol),
-//SOC_SINGLE("Playback 6dB Attenuate", es8323_ADCDAC, 7, 1, 0),
-//SOC_SINGLE("Capture 6dB Attenuate", es8323_ADCDAC, 8, 1, 0),
-
-//SOC_DOUBLE_R_TLV("PCM Volume", ES8323_DACCONTROL4, ES8323_DACCONTROL5, 0, 255, 1, dac_tlv),
-
+SOC_ENUM("Playback De-emphasis", es8323_enum[7]),
+SOC_ENUM("Capture Polarity", es8323_enum[8]),
+SOC_DOUBLE_R_TLV("PCM Volume", ES8323_DACCONTROL4, ES8323_DACCONTROL5, 0, 255, 1, dac_tlv),
SOC_SINGLE_TLV("Left Mixer Left Bypass Volume", ES8323_DACCONTROL17, 3, 7, 1, bypass_tlv),
-/*
-SOC_SINGLE_TLV("Left Mixer Right Bypass Volume", es8323_LOUTM2, 4, 7, 1,
- bypass_tlv),
-SOC_SINGLE_TLV("Right Mixer Left Bypass Volume", es8323_ROUTM1, 4, 7, 1,
- bypass_tlv),
-*/
-SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", ES8323_DACCONTROL20, 3, 7, 1,
- bypass_tlv),
-
-//SOC_DOUBLE_R("Output 1 Playback ZC Switch", es8323_LOUT1V,es8323_ROUT1V, 7, 1, 0),
-SOC_DOUBLE_R_TLV("Output 1 Playback Volume", ES8323_DACCONTROL24, ES8323_DACCONTROL25,
- 0, 64, 0, out_tlv),
-
-//SOC_DOUBLE_R("Output 2 Playback ZC Switch", es8323_LOUT2V,es8323_ROUT2V, 7, 1, 0),
-SOC_DOUBLE_R_TLV("Output 2 Playback Volume", ES8323_DACCONTROL26, ES8323_DACCONTROL27,
- 0, 64, 0, out_tlv),
+SOC_SINGLE_TLV("Right Mixer Right Bypass Volume", ES8323_DACCONTROL20, 3, 7, 1, bypass_tlv),
+SOC_DOUBLE_R_TLV("Output 1 Playback Volume", ES8323_DACCONTROL24, ES8323_DACCONTROL25, 0, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("Output 2 Playback Volume", ES8323_DACCONTROL26, ES8323_DACCONTROL27, 0, 64, 0, out_tlv),
};
-/*
- * DAPM Controls
- */
-/*
-static int es8323_lrc_control(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- u16 adctl2 = snd_soc_read(codec, es8323_ADCTL2);
-*/
- /* Use the DAC to gate LRC if active, otherwise use ADC */
- /*
- if (snd_soc_read(codec, es8323_PWR2) & 0x180)
- adctl2 &= ~0x4;
- else
- adctl2 |= 0x4;
-
- DBG("Enter::%s----%d, adctl2 = %x\n",__FUNCTION__,__LINE__,adctl2);
-
- return snd_soc_write(codec, es8323_ADCTL2, adctl2);
-}
-*/
-static const char *es8323_line_texts[] = {
- "Line 1", "Line 2", "PGA"};
-
-static const unsigned int es8323_line_values[] = {
- 0, 1, 3};
-static const struct soc_enum es8323_lline_enum =
- SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 3, 7,
- ARRAY_SIZE(es8323_line_texts),
- es8323_line_texts,
- es8323_line_values);
static const struct snd_kcontrol_new es8323_left_line_controls =
- SOC_DAPM_VALUE_ENUM("Route", es8323_lline_enum);
+ SOC_DAPM_VALUE_ENUM("Route", es8323_enum[0]);
-static const struct soc_enum es8323_rline_enum =
- SOC_VALUE_ENUM_SINGLE(ES8323_DACCONTROL16, 0, 7,
- ARRAY_SIZE(es8323_line_texts),
- es8323_line_texts,
- es8323_line_values);
static const struct snd_kcontrol_new es8323_right_line_controls =
- SOC_DAPM_VALUE_ENUM("Route", es8323_rline_enum);
+ SOC_DAPM_VALUE_ENUM("Route", es8323_enum[1]);
+
+/* Left PGA Mux */
+static const struct snd_kcontrol_new es8323_left_pga_controls =
+ SOC_DAPM_VALUE_ENUM("Route", es8323_enum[2]);
+/* Right PGA Mux */
+static const struct snd_kcontrol_new es8323_right_pga_controls =
+ SOC_DAPM_VALUE_ENUM("Route", es8323_enum[3]);
/* Left Mixer */
static const struct snd_kcontrol_new es8323_left_mixer_controls[] = {
SOC_DAPM_SINGLE("Left Playback Switch", ES8323_DACCONTROL17, 7, 1, 0),
- SOC_DAPM_SINGLE("Left Bypass Switch", ES8323_DACCONTROL17, 6, 1, 0),
- //SOC_DAPM_SINGLE("Right Playback Switch", es8323_LOUTM2, 8, 1, 0),
- //SOC_DAPM_SINGLE("Right Bypass Switch", es8323_LOUTM2, 7, 1, 0),
+ SOC_DAPM_SINGLE("Left Bypass Switch", ES8323_DACCONTROL17, 6, 1, 0),
};
/* Right Mixer */
static const struct snd_kcontrol_new es8323_right_mixer_controls[] = {
- //SOC_DAPM_SINGLE("Left Playback Switch", es8323_ROUTM1, 8, 1, 0),
- //SOC_DAPM_SINGLE("Left Bypass Switch", es8323_ROUTM1, 7, 1, 0),
SOC_DAPM_SINGLE("Right Playback Switch", ES8323_DACCONTROL20, 7, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", ES8323_DACCONTROL20, 6, 1, 0),
};
-int es8328_dapm_pre_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event);
-int es8328_dapm_post_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event);
-
-static const char *es8323_pga_sel[] = {"Line 1", "Line 2", "Differential"};
-static const unsigned int es8323_pga_val[] = { 0, 1, 3 };
-
-/* Left PGA Mux */
-static const struct soc_enum es8323_lpga_enum =
- SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 6, 3,
- ARRAY_SIZE(es8323_pga_sel),
- es8323_pga_sel,
- es8323_pga_val);
-static const struct snd_kcontrol_new es8323_left_pga_controls =
- SOC_DAPM_VALUE_ENUM("Route", es8323_lpga_enum);
-
-/* Right PGA Mux */
-static const struct soc_enum es8323_rpga_enum =
- SOC_VALUE_ENUM_SINGLE(ES8323_ADCCONTROL2, 4, 3,
- ARRAY_SIZE(es8323_pga_sel),
- es8323_pga_sel,
- es8323_pga_val);
-static const struct snd_kcontrol_new es8323_right_pga_controls =
- SOC_DAPM_VALUE_ENUM("Route", es8323_rpga_enum);
-
/* Differential Mux */
-static const char *es8323_diff_sel[] = {"Line 1", "Line 2"};
-static const struct soc_enum diffmux =
- SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 7, 2, es8323_diff_sel);
+//static const char *es8323_diff_sel[] = {"Line 1", "Line 2"};
static const struct snd_kcontrol_new es8323_diffmux_controls =
- SOC_DAPM_ENUM("Route", diffmux);
+ SOC_DAPM_ENUM("Route", es8323_enum[10]);
/* Mono ADC Mux */
-static const char *es8323_mono_mux[] = {"Stereo", "Mono (Left)",
- "Mono (Right)"};
-static const struct soc_enum monomux =
- SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 3, 3, es8323_mono_mux);
static const struct snd_kcontrol_new es8323_monomux_controls =
- SOC_DAPM_ENUM("Route", monomux);
+ SOC_DAPM_ENUM("Route", es8323_enum[9]);
static const struct snd_soc_dapm_widget es8323_dapm_widgets[] = {
+#if 1
+ SND_SOC_DAPM_INPUT("LINPUT1"),
+ SND_SOC_DAPM_INPUT("LINPUT2"),
+ SND_SOC_DAPM_INPUT("RINPUT1"),
+ SND_SOC_DAPM_INPUT("RINPUT2"),
+
SND_SOC_DAPM_MICBIAS("Mic Bias", ES8323_ADCPOWER, 3, 1),
SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", ES8323_ADCPOWER, 5, 1),
/* gModify.Cmmt Implement when suspend/startup */
- /*SND_SOC_DAPM_DAC("Right DAC", "Right Playback", es8323_PWR2, 7, 0),*/
- /*SND_SOC_DAPM_DAC("Left DAC", "Left Playback", es8323_PWR2, 8, 0),*/
+ SND_SOC_DAPM_DAC("Right DAC", "Right Playback", ES8323_DACPOWER, 7, 0),
+ SND_SOC_DAPM_DAC("Left DAC", "Left Playback", ES8323_DACPOWER, 8, 0),
SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
&es8323_left_mixer_controls[0],
SND_SOC_DAPM_PGA("Left Out 2", ES8323_DACPOWER, 3, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right Out 1", ES8323_DACPOWER, 4, 0, NULL, 0),
SND_SOC_DAPM_PGA("Left Out 1", ES8323_DACPOWER, 5, 0, NULL, 0),
-
- //SND_SOC_DAPM_POST("LRC control", es8323_lrc_control),
+ SND_SOC_DAPM_PGA("LAMP", ES8323_ADCCONTROL1, 4, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("RAMP", ES8323_ADCCONTROL1, 0, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("LOUT1"),
SND_SOC_DAPM_OUTPUT("ROUT1"),
SND_SOC_DAPM_OUTPUT("ROUT2"),
SND_SOC_DAPM_OUTPUT("VREF"),
- SND_SOC_DAPM_INPUT("LINPUT1"),
- SND_SOC_DAPM_INPUT("LINPUT2"),
- SND_SOC_DAPM_INPUT("RINPUT1"),
- SND_SOC_DAPM_INPUT("RINPUT2"),
- SND_SOC_DAPM_PRE("PRE", es8328_dapm_pre_event),
- SND_SOC_DAPM_POST("POST", es8328_dapm_post_event),
+ SND_SOC_DAPM_PRE("PRE", es8323_dapm_pre_event),
+ SND_SOC_DAPM_POST("POST", es8323_dapm_post_event),
+#endif
};
static const struct snd_soc_dapm_route audio_map[] = {
- { "Left Line Mux", "Line 1", "LINPUT1" },
- { "Left Line Mux", "Line 2", "LINPUT2" },
- { "Left Line Mux", "PGA", "Left PGA Mux" },
- //{ "Left Line Mux", "Differential", "Differential Mux" },
-
- { "Right Line Mux", "Line 1", "RINPUT1" },
- { "Right Line Mux", "Line 2", "RINPUT2" },
- { "Right Line Mux", "PGA", "Right PGA Mux" },
- //{ "Right Line Mux", "Differential", "Differential Mux" },
+ { "Left Line Mux", "NULL", "LINPUT1" },
+ { "Left Line Mux", "NULL", "LINPUT2" },
+ { "Left Line Mux", "NULL", "Left PGA Mux" },
+
+ { "Right Line Mux", "NULL", "RINPUT1" },
+ { "Right Line Mux", "NULL", "RINPUT2" },
+ { "Right Line Mux", "NULL", "Right PGA Mux" },
- { "Left PGA Mux", "Line 1", "LINPUT1" },
- { "Left PGA Mux", "Line 2", "LINPUT2" },
- { "Left PGA Mux", "Differential", "Differential Mux" },
+ { "Left PGA Mux", "LAMP", "LINPUT1" },
+ { "Left PGA Mux", "LAMP", "LINPUT2" },
+ { "Left PGA Mux", "LAMP", "Differential Mux" },
- { "Right PGA Mux", "Line 1", "RINPUT1" },
- { "Right PGA Mux", "Line 2", "RINPUT2" },
- { "Right PGA Mux", "Differential", "Differential Mux" },
+ { "Right PGA Mux", "RAMP", "RINPUT1" },
+ { "Right PGA Mux", "RAMP", "RINPUT2" },
+ { "Right PGA Mux", "RAMP", "Differential Mux" },
- { "Differential Mux", "Line 1", "LINPUT1" },
- { "Differential Mux", "Line 1", "RINPUT1" },
- { "Differential Mux", "Line 2", "LINPUT2" },
- { "Differential Mux", "Line 2", "RINPUT2" },
+ { "Differential Mux", "LAMP", "LINPUT1" },
+ { "Differential Mux", "RAMP", "RINPUT1" },
+ { "Differential Mux", "LAMP", "LINPUT2" },
+ { "Differential Mux", "RAMP", "RINPUT2" },
{ "Left ADC Mux", "Stereo", "Left PGA Mux" },
{ "Left ADC Mux", "Mono (Left)", "Left PGA Mux" },
{ "Left ADC", NULL, "Left ADC Mux" },
{ "Right ADC", NULL, "Right ADC Mux" },
- { "Left Line Mux", "Line 1", "LINPUT1" },
- { "Left Line Mux", "Line 2", "LINPUT2" },
- { "Left Line Mux", "PGA", "Left PGA Mux" },
- //{ "Left Line Mux", "Differential", "Differential Mux" },
+ { "Left Line Mux", "LAMP", "LINPUT1" },
+ { "Left Line Mux", "LAMP", "LINPUT2" },
+ { "Left Line Mux", "LAMP", "Left PGA Mux" },
- { "Right Line Mux", "Line 1", "RINPUT1" },
- { "Right Line Mux", "Line 2", "RINPUT2" },
- { "Right Line Mux", "PGA", "Right PGA Mux" },
- //{ "Right Line Mux", "Differential", "Differential Mux" },
+ { "Right Line Mux", "RAMP", "RINPUT1" },
+ { "Right Line Mux", "RAMP", "RINPUT2" },
+ { "Right Line Mux", "RAMP", "Right PGA Mux" },
{ "Left Mixer", "Left Playback Switch", "Left DAC" },
{ "Left Mixer", "Left Bypass Switch", "Left Line Mux" },
- //{ "Left Mixer", "Right Playback Switch", "Right DAC" },
- //{ "Left Mixer", "Right Bypass Switch", "Right Line Mux" },
- //{ "Right Mixer", "Left Playback Switch", "Left DAC" },
- //{ "Right Mixer", "Left Bypass Switch", "Left Line Mux" },
{ "Right Mixer", "Right Playback Switch", "Right DAC" },
{ "Right Mixer", "Right Bypass Switch", "Right Line Mux" },
{ "ROUT2", NULL, "Right Out 2" },
};
-int es8328_dapm_pre_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event)
+int es8323_dapm_pre_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event)
{
// printk("fun:%s, event:%d\r\n", __FUNCTION__, event);
if (event==1)
}
return 0;
}
-int es8328_dapm_post_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event)
+int es8323_dapm_post_event(struct snd_soc_dapm_widget* widget, struct snd_kcontrol * null, int event)
{
// printk("fun:%s, event:%d\r\n", __FUNCTION__, event);
if (event==8)
static void on_off_ext_amp(int i)
{
- struct snd_soc_codec *codec;
- gpio_set_value(SPK_CON, i);
+ // struct snd_soc_codec *codec;
+ if (set_spk == 0) {
+ return;
+ }
+ if(hp_irq_flag == 0)
+ gpio_set_value(SPK_CON, i); //delete by hjc
+
+ DBG("*** %s() SPEAKER set SPK_CON %d\n", __FUNCTION__, i);
mdelay(50);
#ifdef SPK_CTL
//gpio_direction_output(SPK_CTL, GPIO_LOW);
gpio_set_value(SPK_CTL, i);
- /*snd_soc_write(codec,0x1E,0x1F);
- snd_soc_write(codec,0x1F,0xF7);
- snd_soc_write(codec,0x20,0xFD);
- snd_soc_write(codec,0x21,0xFF);
- snd_soc_write(codec,0x22,0x1F);
- snd_soc_write(codec,0x23,0xF7);
- snd_soc_write(codec,0x24,0xFD);
- snd_soc_write(codec,0x25,0xFF);
- snd_soc_write(codec,0x30,0x18);
- snd_soc_write(codec,0x31,0x18);
- */
- DBG("*** %s() SPEAKER set as %d\n", __FUNCTION__, i);
+ DBG("*** %s() SPEAKER set as %d\n", __FUNCTION__, i);
#endif
#ifdef EAR_CON_PIN
//gpio_direction_output(EAR_CON_PIN, GPIO_LOW);
gpio_set_value(EAR_CON_PIN, i);
- /*snd_soc_write(codec,0x1E,0x01);//for 47uF capacitors ,15db Bass@90Hz,Fs=44100
- snd_soc_write(codec,0x1F,0x84);
- snd_soc_write(codec,0x20,0xED);
- snd_soc_write(codec,0x21,0xAF);
- snd_soc_write(codec,0x22,0x20);
- snd_soc_write(codec,0x23,0x6C);
- snd_soc_write(codec,0x24,0xE9);
- snd_soc_write(codec,0x25,0xBE);
- snd_soc_write(codec,0x30,0x1c);
- snd_soc_write(codec,0x31,0x1c);
- */
DBG("*** %s() HEADPHONE set as %d\n", __FUNCTION__, i);
mdelay(50);
#endif
}
+#if 0
static void es8323_codec_set_spk(bool on)
{
on_off_ext_amp(on);
}
+#endif
{
struct snd_soc_codec *codec = dai->codec;
struct es8323_priv *es8323 = snd_soc_codec_get_drvdata(codec);
- u16 i;
+ // u16 i;
if (!es8323->is_startup) {
es8323->is_startup = 1;
//on_off_ext_amp(0);
snd_soc_write(codec, ES8323_DACCONTROL21, 0x80);
*/
snd_soc_write(codec, ES8323_ADCPOWER, 0x59);
- snd_soc_write(codec, ES8323_DACPOWER, 0x0c);
+ snd_soc_write(codec, ES8323_DACPOWER, 0x3c);
snd_soc_write(codec, ES8323_CHIPPOWER, 0x00);
//on_off_ext_amp(1);
}
static int es8323_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u16 mute_reg = snd_soc_read(codec, ES8323_DACCONTROL3) & 0xfb;
+ // u16 mute_reg = snd_soc_read(codec, ES8323_DACCONTROL3) & 0xfb;
DBG("Enter::%s----%d--mute=%d\n",__FUNCTION__,__LINE__,mute);
if (mute)
//snd_soc_write(codec, ES8323_DACCONTROL3, mute_reg | 0x4);
{
- snd_soc_write(codec, ES8323_DACCONTROL3, 0xe6);//0xe6);
+ snd_soc_write(codec, ES8323_DACCONTROL3, 0x06);//0xe6);
}
else
{
- snd_soc_write(codec, ES8323_DACCONTROL3, 0xe2);//0xe2);
-
+ snd_soc_write(codec, ES8323_DACCONTROL3, 0x02);//0xe2);
+ snd_soc_write(codec, 0x30,0x1e);
+ snd_soc_write(codec, 0x31,0x1e);
}
return 0;
}
-static int es8323_trigger(struct snd_pcm_substream *substream, int status, struct snd_soc_dai *dai)
-{
- if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if(status == SNDRV_PCM_TRIGGER_START){
- //on_off_ext_amp(1);
- }
- else if(status == SNDRV_PCM_TRIGGER_STOP){
- //on_off_ext_amp(0);
- }
- }
-
- return 0;
-}
/////////////////////////////////////////////////////////////////
static int es8323_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct es8323_priv *es8323 = snd_soc_codec_get_drvdata(codec);
- u16 OUT_VOL = snd_soc_read(codec, ES8323_LOUT1_VOL);
-
+ // u16 OUT_VOL = snd_soc_read(codec, ES8323_LOUT1_VOL);
+ // u16 i;
+
DBG("Enter::%s----%d level =%d\n",__FUNCTION__,__LINE__,level);
- u16 i;
switch (level) {
case SND_SOC_BIAS_ON:
es8323->is_biason = 1;
break;
-
case SND_SOC_BIAS_PREPARE:
- snd_soc_write(codec, 0x07, 0x7C);
- snd_soc_write(codec, 0x05, 0x00);
- snd_soc_write(codec, 0x06, 0xFF);
- //snd_soc_write(codec, 0x2b, 0x80);
+ snd_soc_write(codec, ES8323_ANAVOLMANAG, 0x7C);
+ snd_soc_write(codec, ES8323_CHIPLOPOW1, 0x00);
+ snd_soc_write(codec, ES8323_CHIPLOPOW2, 0xFF);
snd_soc_write(codec, ES8323_CHIPPOWER, 0x00);
- //snd_soc_write(codec, ES8323_DACPOWER, 0x0c);
snd_soc_write(codec, ES8323_ADCPOWER, 0x59);
- //snd_soc_write(codec, 0x19, 0x00);
break;
- case SND_SOC_BIAS_STANDBY:
-
- snd_soc_write(codec, 0x07, 0x7C);
- snd_soc_write(codec, 0x05, 0x00);
- snd_soc_write(codec, 0x06, 0xFF);
- //snd_soc_write(codec, 0x2b, 0x80);
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_write(codec, ES8323_ANAVOLMANAG, 0x7C);
+ snd_soc_write(codec, ES8323_CHIPLOPOW1, 0x00);
+ snd_soc_write(codec, ES8323_CHIPLOPOW2, 0xFF);
snd_soc_write(codec, ES8323_CHIPPOWER, 0x00);
- //snd_soc_write(codec, ES8323_DACPOWER, 0x0c);
snd_soc_write(codec, ES8323_ADCPOWER, 0x59);
- //snd_soc_write(codec, 0x19, 0x00);
break;
-
case SND_SOC_BIAS_OFF:
- //snd_soc_write(codec, 0x19, 0x04);
- //snd_soc_write(codec, ES8323_DACPOWER, 0xcc);
- snd_soc_write(codec, 0x07, 0x7B);
- snd_soc_write(codec, 0x05, 0xFF);
- snd_soc_write(codec, 0x06, 0xFF);
+ snd_soc_write(codec, ES8323_ANAVOLMANAG, 0x7B);
+ snd_soc_write(codec, ES8323_CHIPLOPOW1, 0xFF);
+ snd_soc_write(codec, ES8323_CHIPLOPOW2, 0xFF);
snd_soc_write(codec, ES8323_ADCPOWER, 0xFF);
snd_soc_write(codec, ES8323_CHIPPOWER, 0xAA);
.set_fmt = es8323_set_dai_fmt,
.set_sysclk = es8323_set_dai_sysclk,
.digital_mute = es8323_mute,
-// .trigger = es8323_trigger,
};
static struct snd_soc_dai_driver es8323_dai = {
static int es8323_suspend(struct snd_soc_codec *codec, pm_message_t state)
{
- u16 i;
+ // u16 i;
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
#if 0
snd_soc_write(codec, 0x19, 0x06);
snd_soc_write(codec, 0x30, 0x00);
snd_soc_write(codec, 0x31, 0x00);
-
-
- snd_soc_write(codec, ES8323_ADCPOWER, 0xFF);
- snd_soc_write(codec, ES8323_DACPOWER, 0xc0);
- snd_soc_write(codec, ES8323_CHIPPOWER, 0xF3);
- snd_soc_write(codec, 0x00, 0x00);
- snd_soc_write(codec, 0x01, 0x58);
- snd_soc_write(codec, 0x2b, 0x9c);
- msleep(50);
- gpio_set_value(SPK_CON, 0);
- return 0;
+ snd_soc_write(codec, ES8323_ADCPOWER, 0xFF);
+ snd_soc_write(codec, ES8323_DACPOWER, 0xc0);
+ snd_soc_write(codec, ES8323_CHIPPOWER, 0xF3);
+ snd_soc_write(codec, 0x00, 0x00);
+ snd_soc_write(codec, 0x01, 0x58);
+ snd_soc_write(codec, 0x2b, 0x9c);
+ msleep(50);
+ gpio_set_value(SPK_CON, 0);
+ return 0;
}
static int es8323_resume(struct snd_soc_codec *codec)
{
- u16 i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
+ // u16 i;
+ // u8 data[2];
+ // u16 *cache = codec->reg_cache;
snd_soc_write(codec, 0x2b, 0x80);
- snd_soc_write(codec, 0x01, 0x50);
- snd_soc_write(codec, 0x00, 0x36);
-
+ snd_soc_write(codec, 0x01, 0x50);
+ snd_soc_write(codec, 0x00, 0x32);
snd_soc_write(codec, ES8323_CHIPPOWER, 0x00);
snd_soc_write(codec, ES8323_DACPOWER, 0x0c);
snd_soc_write(codec, ES8323_ADCPOWER, 0x59);
-
- snd_soc_write(codec, 0x31, es8323_DEF_VOL);
- snd_soc_write(codec, 0x30, es8323_DEF_VOL);
+ snd_soc_write(codec, 0x31, es8323_DEF_VOL);
+ snd_soc_write(codec, 0x30, es8323_DEF_VOL);
snd_soc_write(codec, 0x19, 0x02);
gpio_set_value(SPK_CON, 1);
return 0;
static int es8323_probe(struct snd_soc_codec *codec)
{
- struct es8323_priv *es8323 = snd_soc_codec_get_drvdata(codec);
+ // struct es8323_priv *es8323 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
- u16 reg,i;
+ unsigned long flags=0;
+ // u16 reg,i;
printk("%s\n", __func__);
#if 0
}
//gpio_set_value(SPK_CON, 1);
gpio_direction_output(SPK_CON,0);
+
+
+ ret = gpio_request(HP_DET, NULL);
+ if (ret != 0) {
+ printk("%s request HP_DET error", __func__);
+ return ret;
+ }
+ gpio_direction_input(HP_DET);
+
+ flags = gpio_get_value(HP_DET) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
+
+ HP_IRQ = gpio_to_irq(HP_DET);
+ if (HP_IRQ){
+ ret = request_irq(HP_IRQ, hp_det_irq_handler, flags, "ES8323", NULL);
+ if(ret == 0){
+ printk("%s:register ISR (irq=%d)\n", __FUNCTION__,HP_IRQ);
+ }
+ else
+ printk("request_irq HP_IRQ failed\n");
+ }
if (codec == NULL) {
dev_err(codec->dev, "Codec device not registered\n");
#if 1
//snd_soc_write(codec, 0x35 , 0xa0);
- //snd_soc_write(codec, 0x36 , 0x08);
- snd_soc_write(codec, 0x2B,0x80);
- snd_soc_write(codec, 0x08,0x00); //ES8388 salve
- snd_soc_write(codec, 0x00,0x36); //
- snd_soc_write(codec, 0x01,0x74);
- snd_soc_write(codec, 0x01,0x50); //PLAYBACK & RECORD Mode,EnRefr=1
- msleep(1200);
- snd_soc_write(codec, 0x04,0xfc); //pdn_ana=0,ibiasgen_pdn=0
- snd_soc_write(codec, 0x03,0x59); //pdn_ana=0,ibiasgen_pdn=0
- snd_soc_write(codec, 0x05,0x00); //pdn_ana=0,ibiasgen_pdn=0
- snd_soc_write(codec, 0x06,0xc3); //pdn_ana=0,ibiasgen_pdn=0
- snd_soc_write(codec, 0x02,0xF0); //START DLL and STM
- snd_soc_write(codec, 0x02,0xc0); //START DLL and STM
- snd_soc_write(codec, 0x09,0x88); //ADC L/R PGA = +24dB
- snd_soc_write(codec, 0x2e, 0x00);
- snd_soc_write(codec, 0x2f, 0x00);
- //----------------------------------------------------------------------------------------------------------------
- snd_soc_write(codec, 0x0a,0xf0); //ADC INPUT=LIN2/RIN2
- snd_soc_write(codec, 0x0b,0x82); //ADC INPUT=LIN2/RIN2 //82
- //-----------------------------------------------------------------------------------------------------------------
- snd_soc_write(codec, 0x0C,0x4c); //I2S-24BIT
- snd_soc_write(codec, 0x0d,0x02); //MCLK/LRCK=256
- snd_soc_write(codec, 0x10,0x00); //ADC Left Volume=0db
- snd_soc_write(codec, 0x11,0x00); //ADC Right Volume=0db
- snd_soc_write(codec, 0x12,0xea); // ALC stereo MAXGAIN: 35.5dB, MINGAIN: +6dB (Record Volume increased!)
- snd_soc_write(codec, 0x13,0xc0);
- snd_soc_write(codec, 0x14,0x05);
- snd_soc_write(codec, 0x15,0x06);
- snd_soc_write(codec, 0x16,0x53);
- snd_soc_write(codec, 0x17,0x18); //I2S-16BIT
- snd_soc_write(codec, 0x18,0x02);
- snd_soc_write(codec, 0x1A,0x0A); //DAC VOLUME=0DB
- snd_soc_write(codec, 0x1B,0x0A);
- /***********************/
- snd_soc_write(codec, 0x1E,0x01); //for 47uF capacitors ,15db Bass@90Hz,Fs=44100
- snd_soc_write(codec, 0x1F,0x84);
- snd_soc_write(codec, 0x20,0xED);
- snd_soc_write(codec, 0x21,0xAF);
- snd_soc_write(codec, 0x22,0x20);
- snd_soc_write(codec, 0x23,0x6C);
- snd_soc_write(codec, 0x24,0xE9);
- snd_soc_write(codec, 0x25,0xBE);
- /***********************/
- snd_soc_write(codec, 0x26,0x12); //Left DAC TO Left MIXER
- snd_soc_write(codec, 0x27,0xb8); //Left DAC TO Left MIXER
- snd_soc_write(codec, 0x28,0x38);
- snd_soc_write(codec, 0x29,0x38);
- snd_soc_write(codec, 0x2A,0xb8);
- snd_soc_write(codec, 0x2e,0x00);
- snd_soc_write(codec, 0x2f,0x00);
- snd_soc_write(codec, 0x30,0x00);
- snd_soc_write(codec, 0x31,0x00);
- snd_soc_write(codec, 0x02,0x00); //aa //START DLL and state-machine,START DSM
- snd_soc_write(codec, 0x04,0x3c);
- snd_soc_write(codec, 0x19,0xe2); //SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE
-
-
+ //snd_soc_write(codec, 0x36 , 0x08); //for 1.8V VDD
+snd_soc_write(codec, 0x02,0xf3);
+snd_soc_write(codec, 0x2B,0x80);
+snd_soc_write(codec, 0x08,0x00); //ES8388 salve
+snd_soc_write(codec, 0x00,0x32); //
+snd_soc_write(codec, 0x01,0x72); //PLAYBACK & RECORD Mode,EnRefr=1
+snd_soc_write(codec, 0x03,0x59); //pdn_ana=0,ibiasgen_pdn=0
+snd_soc_write(codec, 0x05,0x00); //pdn_ana=0,ibiasgen_pdn=0
+snd_soc_write(codec, 0x06,0xc3); //pdn_ana=0,ibiasgen_pdn=0
+snd_soc_write(codec, 0x09,0x88); //ADC L/R PGA = +24dB
+//----------------------------------------------------------------------------------------------------------------
+snd_soc_write(codec, 0x0a,0xf0); //ADC INPUT=LIN2/RIN2
+snd_soc_write(codec, 0x0b,0x82); //ADC INPUT=LIN2/RIN2 //82
+//-----------------------------------------------------------------------------------------------------------------
+snd_soc_write(codec, 0x0C,0x4c); //I2S-24BIT
+snd_soc_write(codec, 0x0d,0x02); //MCLK/LRCK=256
+snd_soc_write(codec, 0x10,0x00); //ADC Left Volume=0db
+snd_soc_write(codec, 0x11,0x00); //ADC Right Volume=0db
+snd_soc_write(codec, 0x12,0xea); // ALC stereo MAXGAIN: 35.5dB, MINGAIN: +6dB (Record Volume increased!)
+snd_soc_write(codec, 0x13,0xc0);
+snd_soc_write(codec, 0x14,0x05);
+snd_soc_write(codec, 0x15,0x06);
+snd_soc_write(codec, 0x16,0x53);
+snd_soc_write(codec, 0x17,0x18); //I2S-16BIT
+snd_soc_write(codec, 0x18,0x02);
+snd_soc_write(codec, 0x1A,0x00); //DAC VOLUME=0DB
+snd_soc_write(codec, 0x1B,0x00);
+ /*
+ snd_soc_write(codec, 0x1E,0x01); //for 47uF capacitors ,15db Bass@90Hz,Fs=44100
+ snd_soc_write(codec, 0x1F,0x84);
+ snd_soc_write(codec, 0x20,0xED);
+ snd_soc_write(codec, 0x21,0xAF);
+ snd_soc_write(codec, 0x22,0x20);
+ snd_soc_write(codec, 0x23,0x6C);
+ snd_soc_write(codec, 0x24,0xE9);
+ snd_soc_write(codec, 0x25,0xBE);
+ */
+snd_soc_write(codec, 0x26,0x12); //Left DAC TO Left IXER
+snd_soc_write(codec, 0x27,0xb8); //Left DAC TO Left MIXER
+snd_soc_write(codec, 0x28,0x38);
+snd_soc_write(codec, 0x29,0x38);
+snd_soc_write(codec, 0x2A,0xb8);
+snd_soc_write(codec, 0x02,0x00); //aa //START DLL and state-machine,START DSM
+snd_soc_write(codec, 0x19,0x02); //SOFT RAMP RATE=32LRCKS/STEP,Enable ZERO-CROSS CHECK,DAC MUTE
+snd_soc_write(codec, 0x04,0x0c); //pdn_ana=0,ibiasgen_pdn=0
+msleep(100);
+snd_soc_write(codec, 0x2e,0x00);
+snd_soc_write(codec, 0x2f,0x00);
+snd_soc_write(codec, 0x30,0x08);
+snd_soc_write(codec, 0x31,0x08);
+msleep(200);
+snd_soc_write(codec, 0x30,0x0f);
+snd_soc_write(codec, 0x31,0x0f);
+msleep(200);
+snd_soc_write(codec, 0x30,0x18);
+snd_soc_write(codec, 0x31,0x18);
+msleep(100);
+snd_soc_write(codec, 0x04,0x2c); //pdn_ana=0,ibiasgen_pdn=0
#endif
//s8323_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
void codec_set_spk(bool on)
{
- struct snd_soc_codec *codec = es8323_codec;
-
- DBG("Enter::%s----%d--\n",__FUNCTION__,__LINE__);
-
- if (!on)
- //snd_soc_write(codec, ES8323_DACCONTROL3, mute_reg | 0x4);
- {
- snd_soc_write(codec, ES8323_DACCONTROL3, 0x06);//0xe6);
-
- }
- else
- {
-
- snd_soc_write(codec, ES8323_DACCONTROL3, 0x02);//0xe2);
+ DBG("Enter::%s----%d--, on = %d\n",__FUNCTION__,__LINE__, on);
-
-
- }
- on_off_ext_amp(on);
+ set_spk = on;
+ gpio_set_value(SPK_CON, on);
//return;
}
//.volatile_register = es8323_volatile_register,
//.readable_register = es8323_readable_register,
.reg_cache_step = 1,
+#if 0
.controls = es8323_snd_controls,
.num_controls = ARRAY_SIZE(es8323_snd_controls),
.dapm_routes = audio_map,
//--------------------------------------------------
.read = es8323_read_reg_cache,
.write = es8323_write,
+#endif
};
#if defined(CONFIG_SPI_MASTER)
i2c_set_clientdata(i2c, es8323);
es8323->control_type = SND_SOC_I2C;
- reg = ES8323_IFACE;
- ret = i2c_master_reg8_recv(i2c,reg, &tmp, 1 ,200 * 1000);
+ reg = ES8323_DACCONTROL18;
+ ret = i2c_master_reg8_recv(i2c, reg, &tmp, 1 ,200 * 1000);
//ret =i2c_master_reg8_recv(client, 0x00, buf, 2, 200*1000);//i2c_write_bytes(client, &test_data, 1); //Test I2C connection.
if (ret < 0){
printk("es8323 probe error\n");
return ret;
}
- printk("es8323 probe ok\n");
+ printk("es8323 probe i2c recv ok\n");
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_es8323, &es8323_dai, 1);
return -ENOMEM;
}
es8323_dev = device_create(es8323_class, NULL, MKDEV(0, 1), NULL, "dev");
- device_create_file(es8323_dev, &dev_attr_es8323);
+ ret = device_create_file(es8323_dev, &dev_attr_es8323);
+ if (ret < 0)
+ printk("failed to add dev_attr_es8323 file\n");
return ret;
}
void es8323_i2c_shutdown(struct i2c_client *client)
{
- printk("Chenzy-------hkw-------%s\n", __func__);
-
- gpio_direction_output(SPK_CON,0);
-
-#if 0
-#if 1
- gpio_direction_output(SPK_CON,0);
- //gpio_request(RK30_PIN0_PC7, NULL);
- //gpio_direction_output(RK30_PIN0_PC7,0);
-#endif
+ printk("Chenzy-------hkw-------%s\n", __func__);
+ gpio_direction_output(SPK_CON,0);
- on_off_ext_amp(0);
- // es8323_set_bias_level(es8323_codec, SND_SOC_BIAS_OFF);
-
-//#define SPK_CTL RK29_PIN6_PB6
-// #ifdef SPK_CTL
-// //gpio_direction_output(SPK_CTL, GPIO_LOW);
-// gpio_set_value(SPK_CTL, i);
-// DBG("*** %s() SPEAKER set as %d\n", __FUNCTION__, i);
-// #endif
-//#undef SPK_CTL
- u16 i;
- snd_soc_write(es8323_codec, ES8323_DACCONTROL3, 0x06);//0xe6);
- for(i = 0; i <= 0x1d; i++)
- {
- snd_soc_write(es8323_codec, ES8323_LOUT2_VOL, 0x1d - i);//0x1c); //
- snd_soc_write(es8323_codec, ES8323_ROUT2_VOL, 0x1d - i);//0x1c); //
- }
- snd_soc_write(es8323_codec, ES8323_ADCPOWER, 0xFF);
- snd_soc_write(es8323_codec, ES8323_DACPOWER, 0xFC);
+ snd_soc_write(es8323_codec, ES8323_CONTROL2, 0x58);
+ snd_soc_write(es8323_codec, ES8323_CONTROL1, 0x32);
snd_soc_write(es8323_codec, ES8323_CHIPPOWER, 0xf3);
-#endif
- return 0;
-
- mdelay(100);
+ snd_soc_write(es8323_codec, ES8323_DACPOWER, 0xc0);
+
+ snd_soc_write(es8323_codec, ES8323_DACCONTROL26, 0x00);
+ snd_soc_write(es8323_codec, ES8323_DACCONTROL27, 0x00);
+
+ snd_soc_write(es8323_codec, ES8323_CONTROL1, 0x30);
+ snd_soc_write(es8323_codec, ES8323_CONTROL1, 0x34);
+
+ mdelay(100);
}
#define I2C_CLK_NAME GPIO0B0_I2S8CHCLK_NAME
#define I2C_CLK_GPIO_MODE GPIO0B_GPIO0B0
#define I2C_MGPIO_OUTPUT GPIO_LOW
#define I2C_MCLK_CLK_MODE GPIO0B_I2S_8CH_SCLK
#define I2C_MCLK_GPIO RK30_PIN0_PB1
-static int es8323_i2c_suspend (struct i2c_client *client)
+static int es8323_i2c_suspend (struct i2c_client *client, pm_message_t mesg)
{
#if 0
rk30_mux_api_set(I2C_CLK_NAME,I2C_CLK_GPIO_MODE);
static int __init es8323_modinit(void)
{
- //if(0 == tcsi_get_value(TCSI_CODEC_ES8323))
- // return;
-#if 1
- //extern int get_sound_card_exist() ;
- //extern void set_sound_card_exist(int i) ;
- //extern int i2c0_prober_verify(u32 dev_addr, u16 reg, u32 reg_addr_len, u32 reg_val_len, u32 id);
- //typedef void (*fp_codec_set_spk)(bool on);
- //extern void set_codec_set_spk(fp_codec_set_spk fp);
- //if(get_sound_card_exist()) {
- // printk("%s():Sound card already exist!\n", __FUNCTION__);
- // return -ENODEV;
- //}
- //if(i2c0_prober_verify(0x10, 0x35, 1, 1, 0x0000) != 0) {
- // printk("%s(): Ping error with 0x1a\n", __FUNCTION__);
- // return -ENODEV;
- //}
- //else
- // printk("%s(): Ping OK with 0x1a\n", __FUNCTION__);
- //set_sound_card_exist(0x8323);
- //set_codec_set_spk(es8323_codec_set_spk);
-#endif
return i2c_add_driver(&es8323_i2c_driver);
}
module_init(es8323_modinit);