add support for newton board

This commit is contained in:
蔡枫
2011-06-24 22:39:48 +08:00
parent 328ac983a4
commit 7902882ebb
20 changed files with 7940 additions and 1 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -214,6 +214,14 @@ struct it7260_platform_data {
void (*exit_platform_hw)(void);
};
struct ft5406_platform_data {
int (*get_pendown_state)(void);
int (*init_platform_hw)(void);
int (*ft5406_platform_sleep)(void);
int (*ft5406_platform_wakeup)(void);
void (*exit_platform_hw)(void);
};
struct akm8975_platform_data {
char layouts[3][3];
char project_name[64];

View File

@@ -758,4 +758,13 @@ config TOUCHSCREEN_GT818_IIC
config D70_L3188A
tristate "D70-L3188A based touchscreens"
depends on I2C2_RK29
config TOUCHSCREEN_FT5406
tristate "FT5406 based touchscreens: FT5406 Interface"
depends on I2C2_RK29
help
say Y here if you have a touchscreen interface using the FT5406
controller,and your board-specific initialization code includes that
in its table of I2C devices.
If unsure, say N(but it's safe to say "Y").
endif

View File

@@ -57,4 +57,5 @@ obj-$(CONFIG_TOUCHSCREEN_GT801_IIC) += gt801_ts.o
obj-$(CONFIG_TOUCHSCREEN_GT818_IIC) += gt818_ts.o
obj-$(CONFIG_TOUCHSCREEN_ILI2102_IIC) += ili2102_ts.o
obj-$(CONFIG_D70_L3188A) += goodix_touch.o
obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5406_ts.o

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
#ifndef __LINUX_FT5X0X_TS_H__
#define __LINUX_FT5X0X_TS_H__
#define SCREEN_MAX_X 1024 //800
#define SCREEN_MAX_Y 768 //480
#define PRESS_MAX 255
#define FT5X0X_NAME "ft5x0x_ts"//"synaptics_i2c_rmi"//"synaptics-rmi-ts"//
struct ft5x0x_ts_platform_data{
u16 intr; /* irq number */
};
enum ft5x0x_ts_regs {
FT5X0X_REG_PMODE = 0xA5, /* Power Consume Mode */
};
//FT5X0X_REG_PMODE
#define PMODE_ACTIVE 0x00
#define PMODE_MONITOR 0x01
#define PMODE_STANDBY 0x02
#define PMODE_HIBERNATE 0x03
#ifndef ABS_MT_TOUCH_MAJOR
#define ABS_MT_TOUCH_MAJOR 0x30 /* touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* (omit if circular) */
#define ABS_MT_WIDTH_MAJOR 0x32 /* approaching ellipse */
#define ABS_MT_WIDTH_MINOR 0x33 /* (omit if circular) */
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
#define ABS_MT_BLOB_ID 0x38 /* Group set of pkts as blob */
#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */
#endif /* ABS_MT_TOUCH_MAJOR */
#endif

View File

@@ -155,6 +155,13 @@ config RTC_HYM8563
This driver can also be built as a module. If so, the module
will be called rtc-HYM8563.
config RTC_DRV_M41T66
tristate "ST M41T66"
help
If you say Y here you will get support for the ST M41T66.
This driver can also be built as a module. If so, the module
will be called rtc-m41t80.
config RTC_DRV_DS1307
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
help

View File

@@ -90,3 +90,5 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_HYM8563) += rtc-HYM8563.o
obj-$(CONFIG_RTC_DRV_M41T66) += rtc-m41t66.o

813
drivers/rtc/rtc-m41t66.c Executable file
View File

@@ -0,0 +1,813 @@
/*
* I2C client/driver for the ST M41T62 family of i2c rtc chips.
*
* Author: lhh <lhh@rock-chips.com>
*Port to rk29 by yxj
*
* Based on m41t00.c by Mark A. Greer <mgreer@mvista.com>
*
* 2010 (c) rockchip
*
* 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/bcd.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/string.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/delay.h>
#include <linux/wakelock.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#define M41T62_REG_SSEC 0
#define M41T62_REG_SEC 1
#define M41T62_REG_MIN 2
#define M41T62_REG_HOUR 3
#define M41T62_REG_SQWDAY 4
#define M41T62_REG_DAY 5
#define M41T62_REG_MON 6
#define M41T62_REG_YEAR 7
#define M41T62_REG_ALARM_MON 0xa
#define M41T62_REG_ALARM_DAY 0xb
#define M41T62_REG_ALARM_HOUR 0xc
#define M41T62_REG_ALARM_MIN 0xd
#define M41T62_REG_ALARM_SEC 0xe
#define M41T62_REG_FLAGS 0xf
#define M41T62_REG_SQW 0x13
#define M41T62_REG_SEC_INDEX (M41T62_REG_SEC - 1)
#define M41T62_REG_MIN_INDEX (M41T62_REG_MIN - 1)
#define M41T62_REG_HOUR_INDEX (M41T62_REG_HOUR - 1)
#define M41T62_REG_SQWDAY_INDEX (M41T62_REG_SQWDAY - 1)
#define M41T62_REG_DAY_INDEX (M41T62_REG_DAY - 1)
#define M41T62_REG_MON_INDEX (M41T62_REG_MON - 1)
#define M41T62_REG_YEAR_INDEX (M41T62_REG_YEAR - 1)
#define M41T62_DATETIME_REG_SIZE (M41T62_REG_YEAR )
#define M41T62_REG_ALARM_MON_INDEX (M41T62_REG_ALARM_MON-0x0a)
#define M41T62_REG_ALARM_DAY_INDEX (M41T62_REG_ALARM_DAY-0x0a)
#define M41T62_REG_ALARM_HOUR_INDEX (M41T62_REG_ALARM_HOUR-0x0a)
#define M41T62_REG_ALARM_MIN_INDEX (M41T62_REG_ALARM_MIN-0x0a)
#define M41T62_REG_ALARM_SEC_INDEX (M41T62_REG_ALARM_SEC-0x0a)
#define M41T62_REG_FLAGS_INDEX (M41T62_REG_FLAGS-0x0a)
#define M41T62_ALARM_REG_SIZE \
(M41T62_REG_FLAGS + 1 - M41T62_REG_ALARM_MON)
#define M41T62_SEC_ST (1 << 7) /* ST: Stop Bit */
#define M41T62_ALMON_AFE (1 << 7) /* AFE: alarm flag Enable Bit */
#define M41T62_ALMON_SQWE (1 << 6) /* SQWE: SQW Enable Bit */
//#define M41T62_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */
#define M41T62_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */
//#define M41T62_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */
#define M41T62_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */
#define M41T62_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */
#define M41T62_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */
//#define M41T62_FEATURE_HT (1 << 0) /* Halt feature */
//#define M41T62_FEATURE_BL (1 << 1) /* Battery low indicator */
//#define M41T62_FEATURE_SQ (1 << 2) /* Squarewave feature */
//#define M41T62_FEATURE_WD (1 << 3) /* Extra watchdog resolution */
//#define M41T62_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */
#define REPEAT_SEC 5
#define REPEAT_MIN 4
#define REPEAT_HOUR 3
#define REPEAT_DAY 2
#define REPEAT_MON 1
#define REPEAT_YEAR 0
#define RTC_SPEED 100 * 1000
#define DRV_VERSION "0.05"
#define DRV_NAME "rtc-M41T62"
#if 0
#define DBG(x...) printk(KERN_INFO "rtc-M41T62:" x)
#else
#define DBG(x...)
#endif
//static struct semaphore rtc_sem;//Ryan
struct rock_rtc {
int irq;
struct i2c_client *client;
struct work_struct work;
struct mutex mutex;
struct rtc_device *rtc;
int exiting;
struct rtc_wkalrm alarm;
struct wake_lock wake_lock;
};
static int rtc_alarm_repeat_set(int mod)
{
return 0;
}
static irqreturn_t rtc_wakeup_irq(int irq, void *dev_id)
{
struct rock_rtc *rk_rtc = (struct rock_rtc *)dev_id;
DBG("enter %s\n",__func__);
disable_irq_nosync(irq);
schedule_work(&rk_rtc->work);
return IRQ_HANDLED;
}
static int m41t62_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len)
{
int ret;
ret = i2c_master_reg8_recv(client, reg, buf, len, RTC_SPEED);
if(ret < 0 )
{
printk("%s:rtc m41t62 read reg error\n\n\n",__func__);
}
return ret;
}
static int m41t62_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], __u16 len)
{
int ret;
ret = i2c_master_reg8_send(client, reg, buf, (int)len, RTC_SPEED);
if(ret < 0)
{
printk("%s error>>>>>\n",__func__);
}
return ret;
}
static int m41t62_init_device(struct i2c_client *client)
{
//DBG("%s\n",__func__);
u8 alarmbuf[M41T62_ALARM_REG_SIZE];
u8 sqwdayreg;
//read alarm register current value
m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmbuf,M41T62_ALARM_REG_SIZE);
/*DBG("init alarm mon=0x%x, day=0x%x, hour=0x%x, min=0x%x, sec=0x%x, flags=0x%x\n",
alarmbuf[M41T62_REG_ALARM_MON_INDEX],
alarmbuf[M41T62_REG_ALARM_DAY_INDEX],
alarmbuf[M41T62_REG_ALARM_HOUR_INDEX],
alarmbuf[M41T62_REG_ALARM_MIN_INDEX],
alarmbuf[M41T62_REG_ALARM_SEC_INDEX],
alarmbuf[M41T62_REG_FLAGS_INDEX]);*/
//clear alarm register
alarmbuf[M41T62_REG_ALARM_MON_INDEX] &= ~(0x1f | M41T62_ALMON_AFE);
alarmbuf[M41T62_REG_ALARM_DAY_INDEX] = 0;
alarmbuf[M41T62_REG_ALARM_HOUR_INDEX] = 0;
alarmbuf[M41T62_REG_ALARM_MIN_INDEX] = 0;
alarmbuf[M41T62_REG_ALARM_SEC_INDEX] = 0;
alarmbuf[M41T62_REG_FLAGS_INDEX] = 0;
//write alarm register
m41t62_i2c_set_regs(client,M41T62_REG_ALARM_MON,alarmbuf,M41T62_ALARM_REG_SIZE);
//set outclk to 32768HZ
m41t62_i2c_read_regs(client,M41T62_REG_SQWDAY,&sqwdayreg,1);
sqwdayreg =(sqwdayreg|0x10)&0x1f;
m41t62_i2c_set_regs(client,M41T62_REG_SQWDAY,&sqwdayreg,1);
//m41t62_i2c_read_regs(client,M41T62_REG_SQWDAY,&sqwdayreg,1);
//printk("sqwdayreg:0x%x\n",sqwdayreg);
#if 0
sqwdayreg =0;
m41t62_i2c_read_regs(client,M41T62_REG_FLAGS,&sqwdayreg,1); //YLZ++
printk("%s:rtc m41t2 flag_reg = 0x%x\n",__func__,sqwdayreg);
// if(sqwdayreg & 0x04)
{
m41t62_i2c_read_regs(client,M41T62_REG_SEC,&sqwdayreg,1); //YLZ++
printk("%s:rtc m41t2 sec_reg = 0x%x\n",__func__,sqwdayreg);
sqwdayreg |= 0x80;
m41t62_i2c_set_regs(client,M41T62_REG_SEC,&sqwdayreg,1);
sqwdayreg =0x7f;
m41t62_i2c_set_regs(client,M41T62_REG_SEC,&sqwdayreg,1);
m41t62_i2c_read_regs(client,M41T62_REG_SEC,&sqwdayreg,1); //YLZ++
printk("%s:rtc m41t2 sec_reg = 0x%x\n",__func__,sqwdayreg);
}
sqwdayreg =0;
m41t62_i2c_read_regs(client,M41T62_REG_FLAGS,&sqwdayreg,1); //YLZ++
printk("%s:rtc m41t2 atfer flag_reg = 0x%x\n",__func__,sqwdayreg);
#endif
return 0;
}
static int m41t62_get_datetime(struct i2c_client *client,
struct rtc_time *tm)
{
struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
u8 datetime[M41T62_DATETIME_REG_SIZE];
int ret = 0;
mutex_lock(&rk_rtc->mutex);
ret = m41t62_i2c_read_regs(client,M41T62_REG_SEC,datetime,M41T62_DATETIME_REG_SIZE);
if(ret < 0)
{
printk("%s:read date time from rtc m41t2 error\n",__func__);
}
else
{
ret = 0;
}
mutex_unlock(&rk_rtc->mutex);
/*DBG("-------M41T62_REG_SEC=%x--",datetime[M41T62_REG_SEC_INDEX]);
DBG("-------M41T62_REG_MIN=%x--",datetime[M41T62_REG_MIN_INDEX]);
DBG("-------M41T62_REG_HOUR=%x--",datetime[M41T62_REG_HOUR_INDEX]);
DBG("-------M41T62_REG_SQWDAY=%x--",datetime[M41T62_REG_SQWDAY_INDEX]);
DBG("-------M41T62_REG_DAY=%x--",datetime[M41T62_REG_DAY_INDEX]);
DBG("-------M41T62_REG_MON=%x--",datetime[M41T62_REG_MON_INDEX]);
DBG("-------M41T62_REG_YEAR=%x--",datetime[M41T62_REG_YEAR_INDEX]);*/
tm->tm_sec = bcd2bin(datetime[M41T62_REG_SEC_INDEX]& 0x7f);
tm->tm_min = bcd2bin(datetime[M41T62_REG_MIN_INDEX] & 0x7f);
tm->tm_hour = bcd2bin(datetime[M41T62_REG_HOUR_INDEX] & 0x3f);
tm->tm_mday = bcd2bin(datetime[M41T62_REG_DAY_INDEX] & 0x3f);
tm->tm_wday = bcd2bin(datetime[M41T62_REG_SQWDAY_INDEX] & 0x07);
tm->tm_mon = bcd2bin(datetime[M41T62_REG_MON_INDEX] & 0x1f) - 1;
// assume 20YY not 19YY, and ignore the Century Bit
tm->tm_year = bcd2bin(datetime[M41T62_REG_YEAR_INDEX]) + 100;
DBG("%s>>>>%4d-%02d-%02d>>wday:%d>>%02d:%02d:%02d>>\n",
__func__,tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_wday,
tm->tm_hour,tm->tm_min,tm->tm_sec);
if(tm->tm_year < 100)
{
printk(KERN_INFO "%s:the time read from the rtc M41T62 is illegal ,\
we will use the default time:2010.8.2\n",__func__);
tm->tm_sec = 1;
tm->tm_min = 7;
tm->tm_hour = 7;
tm->tm_mday = 2;
tm->tm_wday = 4;
tm->tm_mon = 7;
tm->tm_year = 110;
}
return ret;
}
/* Sets the given date and time to the real time clock. */
static int m41t62_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
int ret = 0;
u8 datetime[M41T62_DATETIME_REG_SIZE];
datetime[M41T62_REG_SEC_INDEX] = bin2bcd(tm->tm_sec);
datetime[M41T62_REG_MIN_INDEX] = bin2bcd(tm->tm_min);
datetime[M41T62_REG_HOUR_INDEX] =bin2bcd(tm->tm_hour) ;
datetime[M41T62_REG_SQWDAY_INDEX] =(tm->tm_wday & 0x07) |0x10;
datetime[M41T62_REG_DAY_INDEX] = bin2bcd(tm->tm_mday);
datetime[M41T62_REG_MON_INDEX] = bin2bcd(tm->tm_mon + 1) ;
/* assume 20YY not 19YY */
datetime[M41T62_REG_YEAR_INDEX] = bin2bcd(tm->tm_year % 100);
printk(KERN_INFO "%s:set time %4d-%02d-%02d %02d:%02d:%02d to rtc \n",__func__,
tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
mutex_lock(&rk_rtc->mutex);
ret = m41t62_i2c_set_regs(client,M41T62_REG_SEC,datetime, M41T62_DATETIME_REG_SIZE);
if(ret < 0)
{
printk(KERN_INFO "%s:set time to rtc m41t62 error\n",__func__);
}
else
{
ret = 0;
}
mutex_unlock(&rk_rtc->mutex);
return ret;
}
static int m41t62_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
//DBG("%s>>>>>>>>>>>\n",__func__);
return m41t62_get_datetime(to_i2c_client(dev), tm);
}
static int m41t62_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
//DBG("%s\n",__func__);
return m41t62_set_datetime(to_i2c_client(dev), tm);
}
#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
static int m41t62_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
int rc;
struct i2c_client *client = to_i2c_client(dev);
DBG("%s>>>>>>>>>%d\n",__func__ ,cmd);
switch (cmd) {
case RTC_AIE_OFF:
case RTC_AIE_ON:
break;
default:
DBG("RTC func m41t62_rtc_ioctl -ENOIOCTLCMD\n");
return -ENOIOCTLCMD;
}
DBG("RTC func m41t62_rtc_ioctl 1\n");
rc = i2c_smbus_read_byte_data(client, M41T62_REG_ALARM_MON);
if (rc < 0)
goto err;
switch (cmd) {
case RTC_AIE_OFF:
rc &= ~M41T62_ALMON_AFE;
break;
case RTC_AIE_ON:
rc |= M41T62_ALMON_AFE;
break;
}
DBG("\n@@@@@@@@@@@RTC func m41t62_rtc_ioctl 2@@@@@@@@@@@@@\n");
if (i2c_smbus_write_byte_data(client, M41T62_REG_ALARM_MON, rc) < 0)
goto err;
DBG("\n@@@@@@@@@@@RTC func m41t62_rtc_ioctl 3@@@@@@@@@@@@@\n");
return 0;
err:
return -EIO;
}
#else
#define m41t62_rtc_ioctl NULL
#endif
static int m41t62_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
//DBG("%s>>>>>>>>>>>>\n",__func__);
struct i2c_client *client = to_i2c_client(dev);
struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
struct rtc_time current_time ;
u8 alarmbuf[M41T62_ALARM_REG_SIZE];
int ret = 0;
mutex_lock(&rk_rtc->mutex);
//read the current value of alarm register
m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmbuf, M41T62_ALARM_REG_SIZE);
mutex_unlock(&rk_rtc->mutex);
//clear alarm register
alarmbuf[M41T62_REG_ALARM_MON_INDEX] &= ~(0x1f | M41T62_ALMON_AFE);
alarmbuf[M41T62_REG_ALARM_DAY_INDEX] = 0;
alarmbuf[M41T62_REG_ALARM_HOUR_INDEX] &= ~(0x3f | 0x80);
alarmbuf[M41T62_REG_ALARM_MIN_INDEX] = 0;
alarmbuf[M41T62_REG_ALARM_SEC_INDEX] = 0;
rk_rtc->alarm = *alarm;
DBG("time write to alarm :%4d-%02d-%02d %02d:%02d:%02d>>enable:%d\n",
alarm->time.tm_year+1900,
alarm->time.tm_mon,
alarm->time.tm_mday,
alarm->time.tm_hour,
alarm->time.tm_min,
alarm->time.tm_sec,
alarm->enabled);
//get current time
m41t62_get_datetime(client,&current_time);
DBG("current time :%4d-%02d-%02d %02d:%02d:%02d>>\n",
current_time.tm_year+1900,
current_time.tm_mon,
current_time.tm_mday,
current_time.tm_hour,
current_time.tm_min,
current_time.tm_sec);
/* offset into rtc's regs */
alarmbuf[M41T62_REG_ALARM_SEC_INDEX] |= alarm->time.tm_sec >= 0 ?bin2bcd(alarm->time.tm_sec) : 0x80;
alarmbuf[M41T62_REG_ALARM_MIN_INDEX] |= alarm->time.tm_min >= 0 ?bin2bcd(alarm->time.tm_min) : 0x80;
alarmbuf[M41T62_REG_ALARM_HOUR_INDEX] |= alarm->time.tm_hour >= 0 ?bin2bcd(alarm->time.tm_hour) : 0x80;
alarmbuf[M41T62_REG_ALARM_DAY_INDEX] |= alarm->time.tm_mday >= 0 ?bin2bcd(alarm->time.tm_mday) : 0x80;
if (alarm->time.tm_mon >= 0)
alarmbuf[M41T62_REG_ALARM_MON_INDEX] |= bin2bcd(alarm->time.tm_mon + 1);
else
alarmbuf[M41T62_REG_ALARM_DAY_INDEX] |= 0x40;
//Ryan@...
//DBG("enable mon day");
alarmbuf[M41T62_REG_ALARM_MON_INDEX] |= M41T62_ALMON_AFE ;
alarmbuf[M41T62_REG_ALARM_DAY_INDEX] |= 0xc0;//mon, day repeat
//reg[M41T62_REG_ALARM_HOUR] |= 0x80;//hour repeat
//reg[M41T62_REG_ALARM_MIN] |= 0x80;//min repeat
//write alarm register
mutex_lock(&rk_rtc->mutex);
ret = m41t62_i2c_set_regs(client,M41T62_REG_ALARM_MON,alarmbuf, M41T62_DATETIME_REG_SIZE);
if(ret < 0)
{
printk(KERN_INFO "%s:set rtc m41t62 alarm error\n",__func__);
}
else
{
ret = 0;
}
mutex_unlock(&rk_rtc->mutex);
return ret;
}
static int m41t62_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
//DBG("%s>>>>>>>>>>>>>\n",__func__);
struct i2c_client *client = to_i2c_client(dev);
struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
u8 alarmreg[M41T62_ALARM_REG_SIZE ]; // all alarm regs and flags
int ret = 0;
mutex_lock(&rk_rtc->mutex);
m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmreg, M41T62_ALARM_REG_SIZE);
mutex_unlock(&rk_rtc->mutex);
//printk("read alarm mon=0x%x, day=0x%x, hour=0x%x, min=0x%x, sec=0x%x, flags=0x%x\n",
// reg[M41T62_REG_ALARM_MON],
// reg[M41T62_REG_ALARM_DAY],
// reg[M41T62_REG_ALARM_HOUR],
// reg[M41T62_REG_ALARM_MIN],
// reg[M41T62_REG_ALARM_SEC],
// reg[M41T62_REG_FLAGS]);
t->time.tm_sec = -1;
t->time.tm_min = -1;
t->time.tm_hour = -1;
t->time.tm_mday = -1;
t->time.tm_mon = -1;
if (!(alarmreg[M41T62_REG_ALARM_SEC_INDEX] & 0x80))
t->time.tm_sec = bcd2bin(alarmreg[M41T62_REG_ALARM_SEC_INDEX] & 0x7f);
if (!(alarmreg[M41T62_REG_ALARM_MIN_INDEX] & 0x80))
t->time.tm_min = bcd2bin(alarmreg[M41T62_REG_ALARM_MIN_INDEX] & 0x7f);
if (!(alarmreg[M41T62_REG_ALARM_HOUR_INDEX] & 0x80))
t->time.tm_hour = bcd2bin(alarmreg[M41T62_REG_ALARM_HOUR_INDEX] & 0x3f);
if (!(alarmreg[M41T62_REG_ALARM_DAY_INDEX] & 0x80))
t->time.tm_mday = bcd2bin(alarmreg[M41T62_REG_ALARM_DAY_INDEX] & 0x3f);
if (!(alarmreg[M41T62_REG_ALARM_DAY_INDEX] & 0x40))
t->time.tm_mon = bcd2bin(alarmreg[M41T62_REG_ALARM_MON_INDEX] & 0x1f) - 1;
t->time.tm_year = -1;
t->time.tm_wday = -1;
t->time.tm_yday = -1;
t->time.tm_isdst = -1;
t->enabled = !!(alarmreg[M41T62_REG_ALARM_MON_INDEX] & M41T62_ALMON_AFE);
t->pending = !!(alarmreg[M41T62_REG_FLAGS_INDEX] & M41T62_FLAGS_AF);
mutex_lock(&rk_rtc->mutex);
ret = m41t62_i2c_read_regs(client,M41T62_REG_ALARM_MON,alarmreg, M41T62_ALARM_REG_SIZE );
if(ret < 0)
{
printk(KERN_INFO "%s:read rtc m41t62 alarm error\n",__func__);
}
else
{
ret = 0;
}
mutex_unlock(&rk_rtc->mutex);
//printk("read alarm2 mon=0x%x, day=0x%x, hour=0x%x, min=0x%x, sec=0x%x, flags=0x%x\n",
// reg[M41T62_REG_ALARM_MON],
// reg[M41T62_REG_ALARM_DAY],
// reg[M41T62_REG_ALARM_HOUR],
// reg[M41T62_REG_ALARM_MIN],
// reg[M41T62_REG_ALARM_SEC],
// reg[M41T62_REG_FLAGS]);
return ret;
}
static void rockrtc_work_func(struct work_struct *work)
{
struct rock_rtc *rk_rtc = container_of(work, struct rock_rtc, work);
struct i2c_client *client = rk_rtc->client;
struct rtc_time now;
u8 flagreg;
DBG("enter %s\n",__func__);
mutex_lock(&rk_rtc->mutex);
m41t62_i2c_read_regs(client,M41T62_REG_FLAGS,&flagreg, 1 );
flagreg &=~M41T62_FLAGS_AF ;
m41t62_i2c_set_regs(client,M41T62_REG_FLAGS,&flagreg, 1 );
mutex_unlock(&rk_rtc->mutex);
m41t62_get_datetime(client ,&now);
mutex_lock(&rk_rtc->mutex);
if (rk_rtc->alarm.enabled && rk_rtc->alarm.time.tm_sec > now.tm_sec)
{
long timeout = rk_rtc->alarm.time.tm_sec - now.tm_sec + 1;
pr_info("stay awake %lds\n", timeout);
wake_lock_timeout(&rk_rtc->wake_lock, timeout * HZ);
}
if (!rk_rtc->exiting)
enable_irq(rk_rtc->irq);
mutex_unlock(&rk_rtc->mutex);
}
static struct rtc_class_ops m41t62_rtc_ops = {
.read_time = m41t62_rtc_read_time,
.set_time = m41t62_rtc_set_time,
.read_alarm = m41t62_rtc_read_alarm,
.set_alarm = m41t62_rtc_set_alarm,
.ioctl = m41t62_rtc_ioctl,
};
#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
static ssize_t m41t62_sysfs_show_flags(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
int val;
val = i2c_smbus_read_byte_data(client, M41T62_REG_FLAGS);
if (val < 0)
return -EIO;
return sprintf(buf, "%#x\n", val);
}
static DEVICE_ATTR(flags, S_IRUGO, m41t62_sysfs_show_flags, NULL);
static ssize_t m41t62_sysfs_show_sqwfreq(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
int val;
val = i2c_smbus_read_byte_data(client, M41T62_REG_SQW);
if (val < 0)
return -EIO;
val = (val >> 4) & 0xf;
switch (val) {
case 0:
break;
case 1:
val = 32768;
break;
default:
val = 32768 >> val;
}
return sprintf(buf, "%d\n", val);
}
static ssize_t m41t62_sysfs_set_sqwfreq(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
int almon, sqw;
int val = simple_strtoul(buf, NULL, 0);
if (val) {
if (!is_power_of_2(val))
return -EINVAL;
val = ilog2(val);
if (val == 15)
val = 1;
else if (val < 14)
val = 15 - val;
else
return -EINVAL;
}
/* disable SQW, set SQW frequency & re-enable */
almon = i2c_smbus_read_byte_data(client, M41T62_REG_ALARM_MON);
if (almon < 0)
return -EIO;
sqw = i2c_smbus_read_byte_data(client, M41T62_REG_SQW);
if (sqw < 0)
return -EIO;
sqw = (sqw & 0x0f) | (val << 4);
if (i2c_smbus_write_byte_data(client, M41T62_REG_ALARM_MON,
almon & ~M41T62_ALMON_SQWE) < 0 ||
i2c_smbus_write_byte_data(client, M41T62_REG_SQW, sqw) < 0)
return -EIO;
if (val && i2c_smbus_write_byte_data(client, M41T62_REG_ALARM_MON,
almon | M41T62_ALMON_SQWE) < 0)
return -EIO;
return count;
}
static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
m41t62_sysfs_show_sqwfreq, m41t62_sysfs_set_sqwfreq);
static struct attribute *attrs[] = {
&dev_attr_flags.attr,
&dev_attr_sqwfreq.attr,
NULL,
};
static struct attribute_group attr_group = {
.attrs = attrs,
};
static int m41t62_sysfs_register(struct device *dev)
{
DBG("\n@@@@@@@@@@@m41t62_sysfs_register@@@@@@@@@@@@@\n");
return sysfs_create_group(&dev->kobj, &attr_group);
}
#else
static int m41t62_sysfs_register(struct device *dev)
{
DBG("\n@@@@@@@@@@@m41t62_sysfs_register@@@@@@@@@@@@@\n");
return 0;
}
#endif
/*
*****************************************************************************
*
* Driver Interface
*
*****************************************************************************
*/
static int __devinit m41t62_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
//DBG("%s>>>>>>>>>>>>>client->flags:%d\n",__func__,client->flags);
int rc = 0;
struct rock_rtc *rk_rtc = NULL;
struct rtc_device *rtc = NULL;
struct rtc_time tm_read, tm = {
.tm_year = 111,
.tm_mon = 2,
.tm_mday = 7,
.tm_wday = 7,
.tm_hour = 12,
.tm_min = 1,
.tm_sec = 8
};
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ){
rc = -ENODEV;
printk("i2c_check_functionality fail\n");
goto exit;
}
rk_rtc = kzalloc(sizeof(struct rock_rtc), GFP_KERNEL);
if (!rk_rtc) {
return -ENOMEM;
}
rtc = rtc_device_register(client->name, &client->dev,
&m41t62_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
rc = PTR_ERR(rtc);
rtc = NULL;
printk("\nm41t62_probe err3\n");
goto exit;
}
rk_rtc->client = client;
rk_rtc->rtc = rtc;
mutex_init(&rk_rtc->mutex);
wake_lock_init(&rk_rtc->wake_lock, WAKE_LOCK_SUSPEND, "rtc_m41t62");
INIT_WORK(&rk_rtc->work, rockrtc_work_func);
i2c_set_clientdata(client, rk_rtc);
rc = m41t62_sysfs_register(&client->dev);
if (rc)
{
printk("\nm41t62_probe err4\n");
goto exit;
}
m41t62_init_device(client);//0323
m41t62_get_datetime(client, &tm_read);
if((tm_read.tm_year < 111 ) |(tm_read.tm_year > 120 ) |(tm_read.tm_mon > 11))
{
m41t62_set_datetime(client, &tm);
printk("%s [%d]run set time \n",__FUNCTION__,__LINE__);
}
if(gpio_request(client->irq, "rtc gpio"))
{
dev_err(&client->dev, "gpio request fail\n");
gpio_free(client->irq);
goto exit;
}
rk_rtc->irq = gpio_to_irq(client->irq);
gpio_pull_updown(client->irq,GPIOPullUp);
if (request_irq(rk_rtc->irq, rtc_wakeup_irq, IRQF_TRIGGER_FALLING, client->dev.driver->name, rk_rtc) < 0)
{
printk("unable to request rtc irq\n");
goto exit;
}
enable_irq_wake(rk_rtc->irq);
return 0;
exit:
if (rtc)
rtc_device_unregister(rtc);
if (rk_rtc)
kfree(rk_rtc);
return rc;
}
static int __devexit m41t62_remove(struct i2c_client *client)
{
struct rock_rtc *rk_rtc = i2c_get_clientdata(client);
if (rk_rtc->irq > 0) {
mutex_lock(&rk_rtc->mutex);
rk_rtc->exiting = 1;
mutex_unlock(&rk_rtc->mutex);
free_irq(rk_rtc->irq, rk_rtc);
cancel_work_sync(&rk_rtc->work);
}
rtc_device_unregister(rk_rtc->rtc);
wake_lock_destroy(&rk_rtc->wake_lock);
kfree(rk_rtc);
rk_rtc = NULL;
return 0;
}
static const struct i2c_device_id m41t62_id[] = {
{ DRV_NAME, 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, m41t62_id);
static struct i2c_driver m41t62_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = m41t62_probe,
.remove = __devexit_p(m41t62_remove),
.id_table = m41t62_id,
};
static int __init m41t62_rtc_init(void)
{
DBG("%s>>>>>>>>>\n",__func__);
return i2c_add_driver(&m41t62_driver);
}
static void __exit m41t62_rtc_exit(void)
{
DBG("%s>>>>>>>>>\n",__func__);
i2c_del_driver(&m41t62_driver);
}
MODULE_AUTHOR("rockchip lhh");
MODULE_DESCRIPTION("ST Microelectronics M41T62 series RTC I2C Client Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
module_init(m41t62_rtc_init);
module_exit(m41t62_rtc_exit);

View File

@@ -54,6 +54,8 @@ config DEFAULT_OUT_HDMI
if you want set HDMI for default panel, android UI size is HDMI default resolution.
config LCD_AT070TNA2
bool "RGB AT070TNA2"
config LCD_AT070TN93
bool "RGB AT070TN93"
endchoice

View File

@@ -29,3 +29,4 @@ obj-$(CONFIG_LCD_LS035Y8DX02A) += lcd_ls035y8dx02a.o
obj-$(CONFIG_LCD_IPS1P5680_V1_E) += lcd_ips1p5680_v1_e.o
obj-$(CONFIG_LCD_MCU_TFT480800_25_E) += lcd_mcu_tft480800_25_e.o
obj-$(CONFIG_LCD_AT070TNA2) += lcd_AT070TNA2.o
obj-$(CONFIG_LCD_AT070TN93) += lcd_at070tn93.o

View File

@@ -0,0 +1,76 @@
#include <linux/fb.h>
#include <linux/delay.h>
#include "../../rk29_fb.h"
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <mach/board.h>
#include "screen.h"
/* Base */
#define OUT_TYPE SCREEN_RGB
#define OUT_FACE OUT_D888_P666
#define OUT_CLK 58500000 // 65000000
#define LCDC_ACLK 500000000//312000000 //29 lcdc axi DMA Ƶ<><C6B5>
/* Timing */
#define H_PW 10
#define H_BP 100
#define H_VD 800
#define H_FP 210
#define V_PW 10
#define V_BP 10
#define V_VD 480
#define V_FP 18
#define LCD_WIDTH 202
#define LCD_HEIGHT 152
/* Other */
#define DCLK_POL 0
#define SWAP_RB 0
void set_lcd_info(struct rk29fb_screen *screen, struct rk29lcd_info *lcd_info )
{
/* screen type & face */
screen->type = OUT_TYPE;
screen->face = OUT_FACE;
/* Screen size */
screen->x_res = H_VD;
screen->y_res = V_VD;
screen->width = LCD_WIDTH;
screen->height = LCD_HEIGHT;
/* Timing */
screen->lcdc_aclk = LCDC_ACLK;
screen->pixclock = OUT_CLK;
screen->left_margin = H_BP;
screen->right_margin = H_FP;
screen->hsync_len = H_PW;
screen->upper_margin = V_BP;
screen->lower_margin = V_FP;
screen->vsync_len = V_PW;
/* Pin polarity */
screen->pin_hsync = 0;
screen->pin_vsync = 0;
screen->pin_den = 0;
screen->pin_dclk = DCLK_POL;
/* Swap rule */
screen->swap_rb = SWAP_RB;
screen->swap_rg = 0;
screen->swap_gb = 0;
screen->swap_delta = 0;
screen->swap_dumy = 0;
/* Operation function*/
screen->init = NULL;
screen->standby = NULL;
}

View File

@@ -53,6 +53,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8974 if I2C
select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8990 if I2C
select SND_SOC_CS42L52 if I2C
select SND_SOC_WM8993 if I2C
select SND_SOC_WM8994 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM9081 if I2C
@@ -217,6 +218,9 @@ config SND_SOC_WM8988
config SND_SOC_WM8990
tristate
config SND_SOC_CS42L52
tristate
config SND_SOC_WM8993
tristate

View File

@@ -33,6 +33,7 @@ snd-soc-wm8900-objs := wm8900.o
snd-soc-alc5621-objs := alc5621.o
snd-soc-alc5631-objs := rt5631.o
snd-soc-rt5625-objs := rt5625.o
snd-soc-cs42l52-objs := cs42l52.o
snd-soc-wm8903-objs := wm8903.o
snd-soc-wm8940-objs := wm8940.o
snd-soc-wm8960-objs := wm8960.o
@@ -89,6 +90,7 @@ obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
obj-$(CONFIG_SND_SOC_alc5621) += snd-soc-alc5621.o
obj-$(CONFIG_SND_SOC_alc5631) += snd-soc-alc5631.o
obj-$(CONFIG_SND_SOC_RT5625) += snd-soc-rt5625.o
obj-$(CONFIG_SND_SOC_CS42L52) += snd-soc-cs42l52.o
obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o

1400
sound/soc/codecs/cs42l52.c Executable file

File diff suppressed because it is too large Load Diff

323
sound/soc/codecs/cs42l52.h Executable file
View File

@@ -0,0 +1,323 @@
/*
* cs42l52.h -- CS42L52 ALSA SoC audio driver
*
* Copyright 2007 CirrusLogic, Inc.
*
* Author: Bo Liu <Bo.Liu@cirrus.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.
* Revision history
* Nov 2007 Initial version.
*/
#ifndef __CS42L52_H__
#define __CS42L52_H__
#include <linux/types.h>
#include <sound/pcm.h>
#define SOC_CS42L52_NAME "CS42L52"
#define SOC_CS42L52_DEFAULT_CLK 12000000
#define SOC_CS42L52_MIN_CLK 11000000
#define SOC_CS42L52_MAX_CLK 27000000
#define SOC_CS42L52_DEFAULT_FORMAT SNDRV_PCM_FMTBIT_S16_LE
#define SOC_CS42L52_DEFAULT_MAX_CHANS 2
#define CS42L52_SYSCLK 1
#define SOC_CS42L52_CHIP_SWICTH (1 << 17)
#define SOC_CS42L52_ALL_IN_ONE (1 << 16)
#define SOC_CS42L52_CHIP_ONE 0x00
#define SOC_CS42L52_CHIP_TWO 0x01
#define SOC_CS42L52_CHIP_THR 0x02
#define SOC_CS42L52_CHIP_MASK 0x0f
#define CS42L52_PB_PIN_INVERRTED (1 << 3)
#define CS42L52_PB_PIN_LOW 0
#define CS42L52_PB_PIN_HIGN 1
#define CS42L52_PB_ALL_ON 2
#define CS42L52_PB_ALL_OFF 3
struct soc_codec_cs42l52 {
void (*machine_handler)(unsigned int codec_num);
u_int max_playback_stream;
u_int max_capture_stream;
u_int num_dai;
u_int pb_pin_sel;
u_int pb_sel;
u_int adc_sel1;
u_int adc_sel2;
u_int mic_sel;
u_int sysclk;
u_int format;
u_int flags;
};
struct soc_codec_cs42l52_data{
int i2c_bus;
u_short i2c_addr;
};
/*
*CS42L52 internal registers
*/
#define CODEC_CS42L52_CHIP 0x01
#define CHIP_ID 0xE0
#define CHIP_ID_MASK 0xF8
#define CHIP_REV_A0 0x00
#define CHIP_REV_A1 0x01
#define CHIP_REV_B0 0x02
#define CHIP_REV_MASK 0x03
#define CODEC_CS42L52_PWCTL1 0x02 //0x01
#define PWCTL1_PDN_CHRG (1 << 7)
#define PWCTL1_PDN_PGAB (1 << 4)
#define PWCTL1_PDN_PGAB_SHIFT 4
#define PWCTL1_PDN_PGAA (1 << 3)
#define PWCTL1_PDN_PGAA_SHIFT 3
#define PWCTL1_PDN_ADCB (1 << 2)
#define PWCTL1_PDN_ADCB_SHIFT 2
#define PWCTL1_PDN_ADCA (1 << 1)
#define PWCTL1_PDN_ADCA_SHIFT 1
#define PWCTL1_PDN_CODEC (1 << 0)
#define CODEC_CS42L52_PWCTL2 0x03 //0x07
#define PWCTL2_OVRDB (1 << 4)
#define PWCTL2_OVRDA (1 << 3)
#define PWCTL2_PDN_MICB (1 << 2)
#define PWCTL2_PDN_MICB_SHIFT 2
#define PWCTL2_PDN_MICA (1 << 1)
#define PWCTL2_PDN_MICA_SHIFT 1
#define PWCTL2_PDN_MICBIAS (1 << 0)
#define PWCTL2_PDN_MICBIAS_SHIFT 0
#define CODEC_CS42L52_PWCTL3 0x04 //0x08
#define PWCTL3_HPB_PDN_SHIFT 6
#define PWCTL3_HPB_ON_LOW 0x00
#define PWCTL3_HPB_ON_HIGH 0x01
#define PWCTL3_HPB_ALWAYS_ON 0x02
#define PWCTL3_HPB_ALWAYS_OFF 0x03
#define PWCTL3_HPA_PDN_SHIFT 4
#define PWCTL3_HPA_ON_LOW 0x00
#define PWCTL3_HPA_ON_HIGH 0x01
#define PWCTL3_HPA_ALWAYS_ON 0x02
#define PWCTL3_HPA_ALWAYS_OFF 0x03
#define PWCTL3_SPKB_PDN_SHIFT 2
#define PWCTL3_SPKB_ON_LOW 0x00
#define PWCTL3_SPKB_ON_HIGH 0x01
#define PWCTL3_SPKB_ALWAYS_ON 0x02
#define PWCTL3_SPKB_ALWAYS_OFF 0x03
#define PWCTL3_SPKA_PDN_SHIFT 0
#define PWCTL3_SPKA_ON_LOW 0x00
#define PWCTL3_SPKA_ON_HIGH 0x01
#define PWCTL3_SPKA_ALWAYS_ON 0x02
#define PWCTL3_SPKA_ALWAYS_OFF 0x03
#define DEFAULT_OUTPUT_STATE 0x05
#define PWCTL3_CONF_MASK 0x03
#define CODEC_CS42L52_CLK_CTL 0x05 //0xa0
#define CLK_CTL_AUTODECT_ENABLE (1 << 7)
#define CLK_CTL_SPEED_SHIFT 5
#define CLK_CTL_S_DS_MODE 0x00
#define CLK_CTL_S_SS_MODE 0x01
#define CLK_CTL_S_HS_MODE 0x02
#define CLK_CTL_S_QS_MODE 0x03
#define CLK_CTL_32K_SR_SHIFT 4
#define CLK_CTL_32K_SR 1
#define CLK_CTL_NOT_32K 0
#define CLK_CTL_27M_MCLK_SHIFT 3
#define CLK_CTL_27M_MCLK 1
#define CLK_CTL_NOT_27M 0
#define CLK_CTL_RATIO_SHIFT 1
#define CLK_CTL_RATIO_128 0x00
#define CLK_CTL_RATIO_125 0x01
#define CLK_CTL_RATIO_132 0x02
#define CLK_CTL_RATIO_136 0x03
#define CLK_CTL_MCLKDIV2 1
#define CLK_CTL_NOT_MCLKDIV2 0
#define CODEC_CS42L52_IFACE_CTL1 0x06 //0
#define IFACE_CTL1_MASTER (1 << 7)
#define IFACE_CTL1_INV_SCLK (1 << 6)
#define IFACE_CTL1_ADC_FMT_I2S (1 << 5)
#define IFACE_CTL1_ADC_FMT_LEFT_J (0 << 5)
#define IFACE_CTL1_DSP_MODE_EN (1 << 4)
#define IFACE_CTL1_DAC_FMT_LEFT_J (0 << 2)
#define IFACE_CTL1_DAC_FMT_I2S (1 << 2)
#define IFACE_CTL1_DAC_FMT_RIGHT_J (2 << 2)
#define IFACE_CTL1_WL_32BIT (0x00)
#define IFACE_CTL1_WL_24BIT (0x01)
#define IFACE_CTL1_WL_20BIT (0x02)
#define IFACE_CTL1_WL_16BIT (0x03)
#define IFACE_CTL1_WL_MASK 0xFFFF
#define CODEC_CS42L52_IFACE_CTL2 0x07 //0
#define IFACE_CTL2_SC_MC_EQ (1 << 6)
#define IFACE_CTL2_LOOPBACK (1 << 5)
#define IFACE_CTL2_S_MODE_OUTPUT_EN (0 << 4)
#define IFACE_CTL2_S_MODE_OUTPUT_HIZ (1 << 4)
#define IFACE_CTL2_HP_SW_INV (1 << 3)
#define IFACE_CTL2_MIC_BIAS_5X 0x00
#define IFACE_CTL2_MIC_BIAS_6X 0x01
#define IFACE_CTL2_MIC_BIAS_7X 0x02
#define IFACE_CTL2_MIC_BIAS_8X 0x03
#define IFACE_CTL2_MIC_BIAS_83X 0x04
#define IFACE_CTL2_MIC_BIAS_91X 0x05
#define CODEC_CS42L52_ADC_PGA_A 0x08 //0x81
#define CODEC_CS42L52_ADC_PGA_B 0x09 //0x81
#define ADC_SEL_SHIFT 5
#define PGA_SEL_SHIFT 0
#define ADC_SEL_AIN1 0x00
#define ADC_SEL_AIN2 0x01
#define ADC_SEL_AIN3 0x02
#define ADC_SEL_AIN4 0x03
#define ADC_SEL_PGA 0x04
#define PGA_SEL_NONE 0x00
#define PGA_SEL_AIN1 0x01
#define PGA_SEL_AIN2 0x02
#define PGA_SEL_AIN3 0x04
#define PGA_SEL_AIN4 0x08
#define PGA_SEL_MIC 0x10
#define PGA_SEL_MIC_AIN1 0x11
#define PGA_SEL_MIC_AIN1_AIN2 0x13
#define CODEC_CS42L52_ANALOG_HPF_CTL 0x0A //0xa5
#define HPF_CTL_ANLGSFTB (1 << 3)
#define HPF_CTL_ANLGSFTA (1 << 0)
#define CODEC_CS42L52_ADC_HPF_FREQ 0x0B //0
#define CODEC_CS42L52_ADC_MISC_CTL 0x0C //0
#define ADC_MISC_CTL_SOURCE_DSP (1 << 6)
#define CODEC_CS42L52_PB_CTL1 0x0D //0x60
#define PB_CTL1_HP_GAIN_SHIFT 5
#define PB_CTL1_HP_GAIN_03959 0x00
#define PB_CTL1_HP_GAIN_04571 0x01
#define PB_CTL1_HP_GAIN_05111 0x02
#define PB_CTL1_HP_GAIN_06047 0x03
#define PB_CTL1_HP_GAIN_07099 0x04
#define PB_CTL1_HP_GAIN_08399 0x05
#define PB_CTL1_HP_GAIN_10000 0x06
#define PB_CTL1_HP_GAIN_11430 0x07
#define PB_CTL1_INV_PCMB (1 << 3)
#define PB_CTL1_INV_PCMA (1 << 2)
#define PB_CTL1_MSTB_MUTE (1 << 1)
#define PB_CTL1_MSTA_MUTE (1 << 0)
#define PB_CTL1_MUTE_MASK 0xFFFC
#define CODEC_CS42L52_MISC_CTL 0x0E //0x02
#define MISC_CTL_DEEMPH (1 << 2)
#define MISC_CTL_DIGSFT (1 << 1)
#define MISC_CTL_DIGZC (1 << 0)
#define CODEC_CS42L52_PB_CTL2 0x0F //0
#define PB_CTL2_HPB_MUTE (1 << 7)
#define PB_CTL2_HPA_MUTE (1 << 6)
#define PB_CTL2_SPKB_MUTE (1 << 5)
#define PB_CTL2_SPKA_MUTE (1 << 4)
#define PB_CTL2_SPK_SWAP (1 << 2)
#define PB_CTL2_SPK_MONO (1 << 1)
#define PB_CTL2_SPK_MUTE50 (1 << 0)
#define CODEC_CS42L52_MICA_CTL 0x10 //0
#define CODEC_CS42L52_MICB_CTL 0x11 //0
#define MIC_CTL_SEL_MIC1 (0 << 6)
#define MIC_CTL_SEL_MIC2 (1 << 6)
#define MIC_CTL_SEL_DIFF (1 << 5)
#define CODEC_CS42L52_PGAA_CTL 0x12 //0
#define CODEC_CS42L52_PGAB_CTL 0x13 //0
#define PGAX_CTL_VOL_12DB 24
#define PGAX_CTL_VOL_6DB 12 /*step size 0.5db*/
#define CODEC_CS42L52_PASSTHRUA_VOL 0x14 //0
#define CODEC_CS42L52_PASSTHRUB_VOL 0x15 //0
#define CODEC_CS42L52_ADCA_VOL 0x16 //0
#define CODEC_CS42L52_ADCB_VOL 0x17 //0
#define ADCX_VOL_24DB 24 /*step size 1db*/
#define ADCX_VOL_12DB 12
#define ADCX_VOL_6DB 6
#define CODEC_CS42L52_ADCA_MIXER_VOL 0x18 // 0x80
#define CODEC_CS42L52_ADCB_MIXER_VOL 0x19 //0x80
#define ADC_MIXER_VOL_12DB 0x18
#define CODEC_CS42L52_PCMA_MIXER_VOL 0x1A //0
#define CODEC_CS42L52_PCMB_MIXER_VOL 0x1B //0
#define CODEC_CS42L52_BEEP_FREQ 0x1C //0
#define CODEC_CS42L52_BEEP_VOL 0x1D //0
#define BEEP_VOL_12DB 0x06
#define CODEC_CS42L52_BEEP_TONE_CTL 0x1E //0
#define CODEC_CS42L52_TONE_CTL 0x1F //0x88
#define CODEC_CS42L52_MASTERA_VOL 0x20 //0
#define CODEC_CS42L52_MASTERB_VOL 0x21 //0
#define CODEC_CS42L52_HPA_VOL 0x22 //0
#define CODEC_CS42L52_HPB_VOL 0x23 //0
#define DEFAULT_HP_VOL 0x00
#define CODEC_CS42L52_SPKA_VOL 0x24 //0
#define CODEC_CS42L52_SPKB_VOL 0x25 //0
#define DEFAULT_SPK_VOL 0x00
#define CODEC_CS42L52_ADC_PCM_MIXER 0x26 //0
#define CODEC_CS42L52_LIMITER_CTL1 0x27 //0
#define CODEC_CS42L52_LIMITER_CTL2 0x28 //0x7f
#define CODEC_CS42L52_LIMITER_AT_RATE 0x29 //0xc0
#define CODEC_CS42L52_ALC_CTL 0x2A //0
#define ALC_CTL_ALCB_ENABLE (1 << 7)
#define ALC_CTL_ALCA_ENABLE (1 << 6)
#define ALC_CTL_FASTEST_ATTACK 0
#define CODEC_CS42L52_ALC_RATE 0x2B //0x3f
#define ALC_SLOWEST_RELEASE 0x3F
#define CODEC_CS42L52_ALC_THRESHOLD 0x2C //0
#define ALC_MAX_RATE_SHIFT 5
#define ALC_MIN_RATE_SHIFT 2
#define ALC_RATE_0DB 0
#define ALC_RATE_3DB 1
#define ALC_RATE_6DB 2
#define CODEC_CS42L52_NOISE_GATE_CTL 0x2D //0
#define NG_ENABLE (1 << 6)
#define NG_THRESHOLD_SHIFT 2
#define NG_MIN_70DB 2
#define NG_DELAY_SHIFT 0
#define NG_DELAY_100MS 1
#define CODEC_CS42L52_CLK_STATUS 0x2E //0
#define CODEC_CS42L52_BATT_COMPEN 0x2F //0
#define CODEC_CS42L52_BATT_LEVEL 0x30 //0
#define CODEC_CS42L52_SPK_STATUS 0x31 //0
#define SPK_STATUS_PIN_SHIFT 3
#define SPK_STATUS_PIN_HIGH 1
#define CODEC_CS42L52_TEM_CTL 0x32 //0x3b
#define CODEC_CS42L52_THE_FOLDBACK 0x33 //0
#define CODEC_CS42L52_CHARGE_PUMP 0x34 //0x5f
#define SOC_CS42L52_REG_NUM 56
extern struct snd_soc_codec_device soc_codec_dev_cs42l52;
extern struct snd_soc_dai soc_cs42l52_dai;
#endif

View File

@@ -74,6 +74,15 @@ config SND_RK29_SOC_WM8994
help
Say Y if you want to add support for SoC audio on rockchip
with the WM8994.
config SND_RK29_SOC_CS42L52
tristate "SoC I2S Audio support for rockchip - CS42L52"
depends on SND_RK29_SOC && I2C_RK29
select SND_RK29_SOC_I2S
select SND_SOC_CS42L52
help
Say Y if you want to add support for SoC audio on rockchip
with the CS42L52.
config SND_RK29_SOC_RK1000
tristate "SoC I2S Audio support for rockchip - RK1000"
@@ -84,7 +93,7 @@ config SND_RK29_SOC_RK1000
Say Y if you want to add support for SoC audio on rockchip
with the RK1000.
if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_alc5621 || SND_RK29_SOC_alc5631 || SND_RK29_SOC_RT5625
if SND_RK29_SOC_WM8988 || SND_RK29_SOC_RK1000 || SND_RK29_SOC_WM8994 || SND_RK29_SOC_WM8900 || SND_RK29_SOC_alc5621 || SND_RK29_SOC_alc5631 || SND_RK29_SOC_RT5625 || SND_RK29_SOC_CS42L52
choice
prompt "Set i2s type"
config SND_RK29_CODEC_SOC_MASTER

View File

@@ -10,6 +10,7 @@ snd-soc-wm8900-objs := rk29_wm8900.o
snd-soc-alc5621-objs := rk29_alc5621.o
snd-soc-alc5631-objs := rk29_rt5631.o
snd-soc-rt5625-objs := rk29_rt5625.o
snd-soc-cs42l52-objs := rk29_cs42l52.o
snd-soc-wm8988-objs := rk29_wm8988.o
snd-soc-rk1000-objs := rk29_rk1000codec.o
snd-soc-wm8994-objs := rk29_wm8994.o
@@ -21,3 +22,4 @@ obj-$(CONFIG_SND_RK29_SOC_alc5621) += snd-soc-alc5621.o
obj-$(CONFIG_SND_RK29_SOC_alc5631) += snd-soc-alc5631.o
obj-$(CONFIG_SND_RK29_SOC_RT5625) += snd-soc-rt5625.o
obj-$(CONFIG_SND_RK29_SOC_RK1000) += snd-soc-rk1000.o
obj-$(CONFIG_SND_RK29_SOC_CS42L52) += snd-soc-cs42l52.o

218
sound/soc/rk29/rk29_cs42l52.c Executable file
View File

@@ -0,0 +1,218 @@
/*
* rk29_cs42l52.c -- SoC audio for rockchip
*
* Driver for rockchip cs42l52 audio
*
* 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 <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <asm/io.h>
#include <mach/hardware.h>
#include <mach/rk29_iomap.h>
#include "../codecs/cs42l52.h"
#include "rk29_pcm.h"
#include "rk29_i2s.h"
#if 1
#define DBG(x...) printk(KERN_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_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
unsigned int pll_out = 0;
unsigned int lrclk = 0;
int ret;
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
/*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)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF))
{
ret = codec_dai->ops->hw_params(substream, params, codec_dai); //by Vincent
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
}
else
{
/* set codec DAI configuration */
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
#endif
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM );
#endif
if (ret < 0)
return ret;
/* set cpu DAI configuration */
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
#endif
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
#endif
if (ret < 0)
return ret;
}
switch(params_rate(params)) {
case 8000:
case 16000:
case 24000:
case 32000:
case 48000:
pll_out = 12288000;
break;
case 11025:
case 22050:
case 44100:
pll_out = 11289600;
break;
default:
DBG("Enter:%s, %d, Error rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
return -EINVAL;
break;
}
DBG("Enter:%s, %d, rate=%d\n",__FUNCTION__,__LINE__,params_rate(params));
#if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER)
//
//
#endif
#if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE)
snd_soc_dai_set_sysclk(cpu_dai, 0, pll_out, 0);
snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_BCLK, (pll_out/4)/params_rate(params)-1);
snd_soc_dai_set_clkdiv(cpu_dai, ROCKCHIP_DIV_MCLK, 3);
#endif
DBG("Enter:%s, %d, LRCK=%d\n",__FUNCTION__,__LINE__,(pll_out/4)/params_rate(params));
return 0;
}
static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
SND_SOC_DAPM_LINE("Audio Out", NULL),
SND_SOC_DAPM_LINE("Line in", NULL),
SND_SOC_DAPM_MIC("Micn", NULL),
SND_SOC_DAPM_MIC("Micp", NULL),
};
static const struct snd_soc_dapm_route audio_map[]= {
{"Audio Out", NULL, "HPA"},
{"Audio Out", NULL, "HPB"},
{"Line in", NULL, "INPUT1A"},
{"Line in", NULL, "INPUT1B"},
{"Micn", NULL, "INPUT2A"},
{"Micp", NULL, "INPUT2B"},
};
/*
* Logic for a cs42l52 as connected on a rockchip board.
*/
static int rk29_cs42l52_init(struct snd_soc_codec *codec)
{
struct snd_soc_dai *codec_dai = &codec->dai[0];
int ret;
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
/* Add specific widgets */
snd_soc_dapm_new_controls(codec, cs42l52_dapm_widgets,
ARRAY_SIZE(cs42l52_dapm_widgets));
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
/* Set up specific audio path audio_mapnects */
snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
snd_soc_dapm_nc_pin(codec, "HPA");
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
snd_soc_dapm_nc_pin(codec, "HPB");
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
snd_soc_dapm_sync(codec);
DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__);
return 0;
}
static struct snd_soc_ops rk29_ops = {
.hw_params = rk29_hw_params,
};
static struct snd_soc_dai_link rk29_dai = {
.name = "CS42L52",
.stream_name = "CS42L52 PCM",
.cpu_dai = &rk29_i2s_dai[0],
.codec_dai = &soc_cs42l52_dai,
.init = rk29_cs42l52_init,
.ops = &rk29_ops,
};
static struct snd_soc_card snd_soc_card_rk29 = {
.name = "RK29_CS42L52",
.platform = &rk29_soc_platform,
.dai_link = &rk29_dai,
.num_links = 1,
};
static struct snd_soc_device rk29_snd_devdata = {
.card = &snd_soc_card_rk29,
.codec_dev = &soc_codec_dev_cs42l52,
};
static struct platform_device *rk29_snd_device;
static int __init audio_card_init(void)
{
int ret =0;
DBG("Enter::%s----%d\n",__FUNCTION__, __LINE__);
rk29_snd_device = platform_device_alloc("soc-audio", -1);
if (!rk29_snd_device) {
DBG("platform device allocation failed\n");
ret = -ENOMEM;
return ret;
}
platform_set_drvdata(rk29_snd_device, &rk29_snd_devdata);
rk29_snd_devdata.dev = &rk29_snd_device->dev;
ret = platform_device_add(rk29_snd_device);
if (ret) {
DBG("platform device add failed\n");
platform_device_put(rk29_snd_device);
}
return ret;
}
static void __exit audio_card_exit(void)
{
platform_device_unregister(rk29_snd_device);
}
module_init(audio_card_init);
module_exit(audio_card_exit);
/* Module information */
MODULE_AUTHOR("rockchip");
MODULE_DESCRIPTION("ROCKCHIP i2s ASoC Interface");
MODULE_LICENSE("GPL");