From f1a558cdc36dc5b120f4e4006fc78e10fe08a638 Mon Sep 17 00:00:00 2001 From: zhangyijie Date: Fri, 23 Nov 2018 10:24:02 +0800 Subject: [PATCH] (CR)[Kane]:kernel:motor add short vibrate(1/2) motor add ram mode for short vibrate Change-Id: Idc7b7c135764d2b2f985c3fd727a9944959cd776 --- drivers/misc/aw8695_haptic/aw8695.c | 5964 +++++++++++--------- drivers/misc/aw8695_haptic/aw8695.h | 124 +- drivers/misc/aw8695_haptic/aw8695_config.h | 12 + drivers/misc/aw8695_haptic/aw8695_reg.h | 557 +- 4 files changed, 3745 insertions(+), 2912 deletions(-) create mode 100644 drivers/misc/aw8695_haptic/aw8695_config.h diff --git a/drivers/misc/aw8695_haptic/aw8695.c b/drivers/misc/aw8695_haptic/aw8695.c index 0bfcadf5c0f9..5bf24bb84623 100644 --- a/drivers/misc/aw8695_haptic/aw8695.c +++ b/drivers/misc/aw8695_haptic/aw8695.c @@ -1,2650 +1,3314 @@ -/* - * aw8695.c aw8695 haptic module - * - * Version: v1.1.3 - * - * Copyright (c) 2018 AWINIC Technology CO., LTD - * - * Author: Nick Li - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "aw8695.h" -#include "aw8695_reg.h" - -/****************************************************** - * - * Marco - * - ******************************************************/ -#define AW8695_I2C_NAME "aw8695_haptic" -#define AW8695_HAPTIC_NAME "aw8695_haptic" - -#define AW8695_VERSION "v1.1.4" - - -#define AWINIC_RAM_UPDATE_DELAY - -#define AW_I2C_RETRIES 2 -#define AW_I2C_RETRY_DELAY 2 -#define AW_READ_CHIPID_RETRIES 5 -#define AW_READ_CHIPID_RETRY_DELAY 2 - -#define AW8695_MAX_DSP_START_TRY_COUNT 10 - - - -#define AW8695_MAX_FIRMWARE_LOAD_CNT 20 - -/****************************************************** - * - * variable - * - ******************************************************/ -#define AW8695_RTP_NAME_MAX 64 -static char *aw8695_ram_name = "aw8695_haptic.bin"; -static char aw8695_rtp_name[][AW8695_RTP_NAME_MAX] = { - {"aw8695_rtp.bin"}, - {"aw8695_rtp_lighthouse.bin"}, - {"aw8695_rtp_silk.bin"}, -}; - -struct aw8695_container *aw8695_rtp; -struct aw8695 *g_aw8695; - -/****************************************************** - * - * functions - * - ******************************************************/ -static void aw8695_interrupt_clear(struct aw8695 *aw8695); - - - /****************************************************** - * - * aw8695 i2c write/read - * - ******************************************************/ -static int aw8695_i2c_write(struct aw8695 *aw8695, - unsigned char reg_addr, unsigned char reg_data) -{ - int ret = -1; - unsigned char cnt = 0; - - while(cnt < AW_I2C_RETRIES) { - ret = i2c_smbus_write_byte_data(aw8695->i2c, reg_addr, reg_data); - if(ret < 0) { - pr_err("%s: i2c_write cnt=%d error=%d\n", __func__, cnt, ret); - } else { - break; - } - cnt ++; - msleep(AW_I2C_RETRY_DELAY); - } - - return ret; -} - -static int aw8695_i2c_read(struct aw8695 *aw8695, - unsigned char reg_addr, unsigned char *reg_data) -{ - int ret = -1; - unsigned char cnt = 0; - - while(cnt < AW_I2C_RETRIES) { - ret = i2c_smbus_read_byte_data(aw8695->i2c, reg_addr); - if(ret < 0) { - pr_err("%s: i2c_read cnt=%d error=%d\n", __func__, cnt, ret); - } else { - *reg_data = ret; - break; - } - cnt ++; - msleep(AW_I2C_RETRY_DELAY); - } - - return ret; -} - -static int aw8695_i2c_write_bits(struct aw8695 *aw8695, - unsigned char reg_addr, unsigned int mask, unsigned char reg_data) -{ - unsigned char reg_val = 0; - - aw8695_i2c_read(aw8695, reg_addr, ®_val); - reg_val &= mask; - reg_val |= reg_data; - aw8695_i2c_write(aw8695, reg_addr, reg_val); - - return 0; -} - -static int aw8695_i2c_writes(struct aw8695 *aw8695, - unsigned char reg_addr, unsigned char *buf, unsigned int len) -{ - int ret = -1; - unsigned char *data; - - data = kmalloc(len+1, GFP_KERNEL); - if (data == NULL) { - pr_err("%s: can not allocate memory\n", __func__); - return -ENOMEM; - } - - data[0] = reg_addr; - memcpy(&data[1], buf, len); - - ret = i2c_master_send(aw8695->i2c, data, len+1); - if (ret < 0) { - pr_err("%s: i2c master send error\n", __func__); - } - - kfree(data); - - return ret; -} - -/***************************************************** - * - * ram update - * - *****************************************************/ -static void aw8695_rtp_loaded(const struct firmware *cont, void *context) -{ - struct aw8695 *aw8695 = context; - pr_info("%s enter\n", __func__); - - if (!cont) { - pr_err("%s: failed to read %s\n", __func__, aw8695_rtp_name[aw8695->rtp_file_num]); - release_firmware(cont); - return; - } - - pr_info("%s: loaded %s - size: %zu\n", __func__, aw8695_rtp_name[aw8695->rtp_file_num], - cont ? cont->size : 0); - - /* aw8695 rtp update */ - aw8695_rtp = kzalloc(cont->size+sizeof(int), GFP_KERNEL); - if (!aw8695_rtp) { - release_firmware(cont); - pr_err("%s: Error allocating memory\n", __func__); - return; - } - aw8695_rtp->len = cont->size; - pr_info("%s: rtp size = %d\n", __func__, aw8695_rtp->len); - memcpy(aw8695_rtp->data, cont->data, cont->size); - release_firmware(cont); - - aw8695->rtp_init = 1; - pr_info("%s: rtp update complete\n", __func__); -} - -static int aw8695_rtp_update(struct aw8695 *aw8695) -{ - pr_info("%s enter\n", __func__); - - return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - aw8695_rtp_name[aw8695->rtp_file_num], aw8695->dev, GFP_KERNEL, - aw8695, aw8695_rtp_loaded); -} - - - static void aw8695_container_update(struct aw8695 *aw8695, - struct aw8695_container *aw8695_cont) -{ - int i = 0; - unsigned int shift = 0; - - pr_info("%s enter\n", __func__); - - mutex_lock(&aw8695->lock); - - aw8695->ram.baseaddr_shift = 2; - aw8695->ram.ram_shift = 4; - - /* RAMINIT Enable */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_EN); - - /* base addr */ - shift = aw8695->ram.baseaddr_shift; - aw8695->ram.base_addr = (unsigned int)((aw8695_cont->data[0+shift]<<8) | - (aw8695_cont->data[1+shift])); - pr_info("%s: base_addr=0x%4x\n", __func__, aw8695->ram.base_addr); - - aw8695_i2c_write(aw8695, AW8695_REG_BASE_ADDRH, aw8695_cont->data[0+shift]); - aw8695_i2c_write(aw8695, AW8695_REG_BASE_ADDRL, aw8695_cont->data[1+shift]); - - aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AEH, - (unsigned char)((aw8695->ram.base_addr>>2)>>8)); - aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AEL, - (unsigned char)((aw8695->ram.base_addr>>2)&0x00FF)); - aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AFH, - (unsigned char)((aw8695->ram.base_addr-(aw8695->ram.base_addr>>2))>>8)); - aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AFL, - (unsigned char)((aw8695->ram.base_addr-(aw8695->ram.base_addr>>2))&0x00FF)); - - /* ram */ - shift = aw8695->ram.baseaddr_shift; - aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRH, aw8695_cont->data[0+shift]); - aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRL, aw8695_cont->data[1+shift]); - shift = aw8695->ram.ram_shift; - for(i=shift; ilen; i++) { - aw8695_i2c_write(aw8695, AW8695_REG_RAMDATA, aw8695_cont->data[i]); - } - -#if 0 - /* ram check */ - shift = aw8695->ram.baseaddr_shift; - aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRH, aw8695_cont->data[0+shift]); - aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRL, aw8695_cont->data[1+shift]); - shift = aw8695->ram.ram_shift; - for(i=shift; ilen; i++) { - aw8695_i2c_read(aw8695, AW8695_REG_RAMDATA, ®_val); - if(reg_val != aw8695_cont->data[i]) { - pr_err("%s: ram check error addr=0x%04x, file_data=0x%02x, ram_data=0x%02x\n", - __func__, i, aw8695_cont->data[i], reg_val); - return; - } - } -#endif - - /* RAMINIT Disable */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_OFF); - - mutex_unlock(&aw8695->lock); - - pr_info("%s exit\n", __func__); -} - - -static void aw8695_ram_loaded(const struct firmware *cont, void *context) -{ - struct aw8695 *aw8695 = context; - struct aw8695_container *aw8695_fw; - int i = 0; - unsigned short check_sum = 0; - - pr_info("%s enter\n", __func__); - - if (!cont) { - pr_err("%s: failed to read %s\n", __func__, aw8695_ram_name); - release_firmware(cont); - return; - } - - pr_info("%s: loaded %s - size: %zu\n", __func__, aw8695_ram_name, - cont ? cont->size : 0); -/* - for(i=0; isize; i++) { - pr_info("%s: addr:0x%04x, data:0x%02x\n", __func__, i, *(cont->data+i)); - } -*/ - - /* check sum */ - for(i=2; isize; i++) { - check_sum += cont->data[i]; - } - if(check_sum != (unsigned short)((cont->data[0]<<8)|(cont->data[1]))) { - pr_err("%s: check sum err: check_sum=0x%04x\n", __func__, check_sum); - return; - } else { - pr_info("%s: check sum pass : 0x%04x\n", __func__, check_sum); - aw8695->ram.check_sum = check_sum; - } - - /* aw8695 ram update */ - aw8695_fw = kzalloc(cont->size+sizeof(int), GFP_KERNEL); - if (!aw8695_fw) { - release_firmware(cont); - pr_err("%s: Error allocating memory\n", __func__); - return; - } - aw8695_fw->len = cont->size; - memcpy(aw8695_fw->data, cont->data, cont->size); - release_firmware(cont); - - aw8695_container_update(aw8695, aw8695_fw); - - aw8695->ram.len = aw8695_fw->len; - - kfree(aw8695_fw); - - aw8695->ram_init = 1; - pr_info("%s: fw update complete\n", __func__); - - aw8695_rtp_update(aw8695); -} - -static int aw8695_ram_update(struct aw8695 *aw8695) -{ - aw8695->ram_init = 0; - aw8695->rtp_init = 0; - return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, - aw8695_ram_name, aw8695->dev, GFP_KERNEL, - aw8695, aw8695_ram_loaded); -} - -#ifdef AWINIC_RAM_UPDATE_DELAY -static void aw8695_ram_work_routine(struct work_struct *work) -{ - struct aw8695 *aw8695 = container_of(work, struct aw8695, ram_work.work); - - pr_info("%s enter\n", __func__); - - aw8695_ram_update(aw8695); - -} -#endif - -static int aw8695_ram_init(struct aw8695 *aw8695) -{ -#ifdef AWINIC_RAM_UPDATE_DELAY - int ram_timer_val = 5000; - INIT_DELAYED_WORK(&aw8695->ram_work, aw8695_ram_work_routine); - schedule_delayed_work(&aw8695->ram_work, msecs_to_jiffies(ram_timer_val)); -#else - aw8695_ram_update(aw8695); -#endif - return 0; -} - - - -/***************************************************** - * - * haptic control - * - *****************************************************/ -static int aw8695_haptic_softreset(struct aw8695 *aw8695) -{ - pr_debug("%s enter\n", __func__); - - aw8695_i2c_write(aw8695, AW8695_REG_ID, 0xAA); - msleep(1); - return 0; -} - -static int aw8695_haptic_active(struct aw8695 *aw8695) -{ - pr_debug("%s enter\n", __func__); - - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_WORK_MODE_MASK, AW8695_BIT_SYSCTRL_ACTIVE); - aw8695_interrupt_clear(aw8695); - return 0; -} - -static int aw8695_haptic_play_mode(struct aw8695 *aw8695, unsigned char play_mode) -{ - pr_debug("%s enter\n", __func__); - - switch(play_mode) { - case AW8695_HAPTIC_STANDBY_MODE: - aw8695->play_mode = AW8695_HAPTIC_STANDBY_MODE; - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_WORK_MODE_MASK, AW8695_BIT_SYSCTRL_STANDBY); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); - break; - case AW8695_HAPTIC_RAM_MODE: - aw8695->play_mode = AW8695_HAPTIC_RAM_MODE; - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RAM); - aw8695_haptic_active(aw8695); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); - break; - case AW8695_HAPTIC_RTP_MODE: - aw8695->play_mode = AW8695_HAPTIC_RTP_MODE; - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RTP); - aw8695_haptic_active(aw8695); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); - break; - case AW8695_HAPTIC_TRIG_MODE: - aw8695->play_mode = AW8695_HAPTIC_TRIG_MODE; - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RAM); - aw8695_haptic_active(aw8695); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); - break; - case AW8695_HAPTIC_CONT_MODE: - aw8695->play_mode = AW8695_HAPTIC_CONT_MODE; - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_CONT); - aw8695_haptic_active(aw8695); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); - break; - default: - dev_err(aw8695->dev, "%s: play mode %d err", - __func__, play_mode); - break; - } - return 0; -} - -static int aw8695_haptic_play_go(struct aw8695 *aw8695, bool flag) -{ - pr_debug("%s enter\n", __func__); - - if(flag == true) { - aw8695_i2c_write_bits(aw8695, AW8695_REG_GO, - AW8695_BIT_GO_MASK, AW8695_BIT_GO_ENABLE); - } else { - aw8695_i2c_write_bits(aw8695, AW8695_REG_GO, - AW8695_BIT_GO_MASK, AW8695_BIT_GO_DISABLE); - } - return 0; -} - - -static int aw8695_haptic_stop(struct aw8695 *aw8695) -{ - pr_debug("%s enter\n", __func__); - - aw8695_haptic_play_go(aw8695, false); - msleep(40); - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_STANDBY_MODE); - - return 0; -} - -static int aw8695_haptic_start(struct aw8695 *aw8695) -{ - pr_debug("%s enter\n", __func__); - - aw8695_haptic_play_go(aw8695, true); - - return 0; -} - -static int aw8695_haptic_set_wav_seq(struct aw8695 *aw8695, - unsigned char wav, unsigned char seq) -{ - aw8695_i2c_write(aw8695, AW8695_REG_WAVSEQ1+wav, - seq); - return 0; -} - -static int aw8695_haptic_set_wav_loop(struct aw8695 *aw8695, - unsigned char wav, unsigned char loop) -{ - unsigned char tmp = 0; - - if(wav%2) { - tmp = loop<<0; - aw8695_i2c_write_bits(aw8695, AW8695_REG_WAVLOOP1+(wav/2), - AW8695_BIT_WAVLOOP_SEQNP1_MASK, tmp); - } else { - tmp = loop<<4; - aw8695_i2c_write_bits(aw8695, AW8695_REG_WAVLOOP1+(wav/2), - AW8695_BIT_WAVLOOP_SEQN_MASK, tmp); - } - - return 0; -} -/* -static int aw8695_haptic_set_main_loop(struct aw8695 *aw8695, - unsigned char loop) -{ - aw8695_i2c_write(aw8695, AW8695_REG_MAIN_LOOP, loop); - return 0; -} -*/ -static int aw8695_haptic_set_repeat_seq(struct aw8695 *aw8695, unsigned char flag) -{ -/* - if(flag) { - aw8695_i2c_write_bits(aw8695, AW8695_REG_DATACTRL, - AW8695_BIT_DATACTRL_WAV_DBG_MASK, AW8695_BIT_DATACTRL_WAV_DBG); - } else { - aw8695_i2c_write_bits(aw8695, AW8695_REG_DATACTRL, - AW8695_BIT_DATACTRL_WAV_DBG_MASK, AW8695_BIT_DATACTRL_WAV_NORMAL); - } -*/ - return 0; -} - -static int aw8695_haptic_set_repeat_wav_seq(struct aw8695 *aw8695, unsigned char seq) -{ -/* - unsigned char i; - for(i=0; ichipid) { - case AW8694_ID: - case AW8695_ID: - if(peak_cur & 0xfc) { - peak_cur = 0x01; - } - break; - case AW8696_ID: - case AW8697_ID: - if(peak_cur & 0xf8) { - peak_cur = 0x05; - } - break; - default: - break; - } - aw8695_i2c_write_bits(aw8695, AW8695_REG_BSTCFG, - AW8695_BIT_BSTCFG_PEAKCUR_MASK, peak_cur); - return 0; -} - -static int aw8695_haptic_set_gain(struct aw8695 *aw8695, unsigned char gain) -{ - aw8695_i2c_write(aw8695, AW8695_REG_DATDBG, gain); - return 0; -} - -static int aw8695_haptic_set_pwm(struct aw8695 *aw8695, unsigned char mode) -{ - switch(mode) { - case AW8695_PWM_48K: - aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMDBG, - AW8695_BIT_PWMDBG_PWM_MODE_MASK, AW8695_BIT_PWMDBG_PWM_48K); - break; - case AW8695_PWM_24K: - aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMDBG, - AW8695_BIT_PWMDBG_PWM_MODE_MASK, AW8695_BIT_PWMDBG_PWM_24K); - break; - case AW8695_PWM_12K: - aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMDBG, - AW8695_BIT_PWMDBG_PWM_MODE_MASK, AW8695_BIT_PWMDBG_PWM_12K); - break; - default: - break; - } - return 0; -} - -static int aw8695_haptic_play_wav_seq(struct aw8695 *aw8695, unsigned char flag) -{ - pr_debug("%s enter\n", __func__); - - //aw8695_haptic_stop(aw8695); - if(flag) { - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); - aw8695_haptic_set_repeat_seq(aw8695, 0); - aw8695_haptic_start(aw8695); - } - return 0; -} -/* -static int aw8695_haptic_play_repeat_seq(struct aw8695 *aw8695, unsigned char flag) -{ - pr_debug("%s enter\n", __func__); - //aw8695_haptic_stop(aw8695); - if(flag) { - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); - aw8695_haptic_set_repeat_seq(aw8695, 1); - aw8695_haptic_start(aw8695); - } - - return 0; -} -*/ -static int aw8695_haptic_set_f0_preset(struct aw8695 *aw8695) -{ - unsigned int f0_reg = 0; - - pr_debug("%s enter\n", __func__); - - f0_reg = 1000000000/(aw8695->f0_pre*AW8695_HAPTIC_F0_COEFF); - aw8695_i2c_write(aw8695, AW8695_REG_F_PRE_H, (unsigned char)((f0_reg>>8)&0xff)); - aw8695_i2c_write(aw8695, AW8695_REG_F_PRE_L, (unsigned char)((f0_reg>>0)&0xff)); - - return 0; -} - -static int aw8695_haptic_get_f0(struct aw8695 *aw8695) -{ - int ret = 0; - unsigned char reg_val = 0; - unsigned int f0_reg = 0; - unsigned long f0_tmp = 0; - - pr_debug("%s enter\n", __func__); - - ret = aw8695_i2c_read(aw8695, AW8695_REG_F_LRA_F0_H, ®_val); - f0_reg = (reg_val<<8); - ret = aw8695_i2c_read(aw8695, AW8695_REG_F_LRA_F0_L, ®_val); - f0_reg |= (reg_val<<0); - f0_tmp = 1000000000/(f0_reg*AW8695_HAPTIC_F0_COEFF); - aw8695->f0 = (unsigned int)f0_tmp; - pr_info("%s f0=%d\n", __func__, aw8695->f0); - - return 0; -} - -static int aw8695_haptic_get_beme(struct aw8695 *aw8695) -{ - int ret = 0; - unsigned char reg_val = 0; - - ret = aw8695_i2c_read(aw8695, AW8695_REG_WAIT_VOL_MP, ®_val); - aw8695->max_pos_beme = (reg_val<<0); - ret = aw8695_i2c_read(aw8695, AW8695_REG_WAIT_VOL_MN, ®_val); - aw8695->max_neg_beme = (reg_val<<0); - - pr_info("%s max_pos_beme=%d\n", __func__, aw8695->max_pos_beme); - pr_info("%s max_neg_beme=%d\n", __func__, aw8695->max_neg_beme); - - return 0; -} - - - -static void aw8695_haptic_set_rtp_aei(struct aw8695 *aw8695, bool flag) -{ - if(flag) { - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_FF_AE_MASK, AW8695_BIT_SYSINTM_FF_AE_EN); - } else { - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_FF_AE_MASK, AW8695_BIT_SYSINTM_FF_AE_OFF); - } -} -/* -static void aw8695_haptic_set_rtp_afi(struct aw8695 *aw8695, bool flag) -{ - if(flag) { - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_FF_AF_MASK, AW8695_BIT_SYSINTM_FF_AF_EN); - } else { - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_FF_AF_MASK, AW8695_BIT_SYSINTM_FF_AF_OFF); - } -} -*/ -/* -static unsigned char aw8695_haptic_rtp_get_fifo_aei(struct aw8695 *aw8695) -{ - unsigned char ret; - unsigned char reg_val; - - aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - reg_val &= AW8695_BIT_SYSINT_FF_AEI; - ret = reg_val>>4; - - return ret; -} -*/ - -static unsigned char aw8695_haptic_rtp_get_fifo_afi(struct aw8695 *aw8695) -{ - unsigned char ret = 0; - unsigned char reg_val = 0; - - aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - reg_val &= AW8695_BIT_SYSINT_FF_AFI; - ret = reg_val>>3; - - return ret; -} - -static int aw8695_haptic_rtp_init(struct aw8695 *aw8695) -{ - unsigned int buf_len = 0; - - pr_info("%s enter\n", __func__); - - aw8695->rtp_cnt = 0; - - while((!aw8695_haptic_rtp_get_fifo_afi(aw8695)) && - (aw8695->play_mode == AW8695_HAPTIC_RTP_MODE)) { - pr_info("%s rtp cnt = %d\n", __func__, aw8695->rtp_cnt); - if((aw8695_rtp->len-aw8695->rtp_cnt) < (aw8695->ram.base_addr>>2)) { - buf_len = aw8695_rtp->len-aw8695->rtp_cnt; - } else { - buf_len = (aw8695->ram.base_addr>>2); - } - aw8695_i2c_writes(aw8695, AW8695_REG_RTP_DATA, - &aw8695_rtp->data[aw8695->rtp_cnt], buf_len); - aw8695->rtp_cnt += buf_len; - if(aw8695->rtp_cnt == aw8695_rtp->len) { - pr_info("%s: rtp update complete\n", __func__); - aw8695->rtp_cnt = 0; - return 0; - } - } - - if(aw8695->play_mode == AW8695_HAPTIC_RTP_MODE) { - aw8695_haptic_set_rtp_aei(aw8695, true); - } - - pr_info("%s exit\n", __func__); - - return 0; -} - -static void aw8695_rtp_work_routine(struct work_struct *work) -{ - const struct firmware *rtp_file; - int ret = -1; - struct aw8695 *aw8695 = container_of(work, struct aw8695, rtp_work); - - pr_info("%s enter\n", __func__); - - /* fw loaded */ - ret = request_firmware(&rtp_file, - aw8695_rtp_name[aw8695->rtp_file_num], - aw8695->dev); - if(ret < 0) - { - pr_err("%s: failed to read %s\n", __func__, - aw8695_rtp_name[aw8695->rtp_file_num]); - return ; - } - aw8695->rtp_init = 0; - kfree(aw8695_rtp); - aw8695_rtp = kzalloc(rtp_file->size+sizeof(int), GFP_KERNEL); - if (!aw8695_rtp) { - release_firmware(rtp_file); - pr_err("%s: error allocating memory\n", __func__); - return; - } - aw8695_rtp->len = rtp_file->size; - pr_info("%s: rtp file [%s] size = %d\n", __func__, - aw8695_rtp_name[aw8695->rtp_file_num], aw8695_rtp->len); - memcpy(aw8695_rtp->data, rtp_file->data, rtp_file->size); - release_firmware(rtp_file); - - aw8695->rtp_init = 1; - - /* rtp mode config */ - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RTP_MODE); - - /* haptic start */ - aw8695_haptic_start(aw8695); - - aw8695_haptic_rtp_init(aw8695); -} - - -/***************************************************** - * - * haptic - audio - * - *****************************************************/ -static enum hrtimer_restart aw8695_haptic_audio_timer_func(struct hrtimer *timer) -{ - struct aw8695 *aw8695 = container_of(timer, struct aw8695, haptic_audio.timer); - - pr_debug("%s enter\n", __func__); - schedule_work(&aw8695->haptic_audio.work); - - hrtimer_start(&aw8695->haptic_audio.timer, - ktime_set(aw8695->haptic_audio.timer_val/1000000, - (aw8695->haptic_audio.timer_val%1000000)*1000), - HRTIMER_MODE_REL); - return HRTIMER_NORESTART; -} - -static void aw8695_haptic_audio_work_routine(struct work_struct *work) -{ - struct aw8695 *aw8695 = container_of(work, struct aw8695, haptic_audio.work); - - pr_debug("%s enter\n", __func__); - - mutex_lock(&aw8695->haptic_audio.lock); - memcpy(&aw8695->haptic_audio.ctr, - &aw8695->haptic_audio.data[aw8695->haptic_audio.cnt], - sizeof(struct haptic_ctr)); - pr_debug("%s: cnt=%d, cmd=%d, play=%d, wavseq=%d, loop=%d, gain=%d\n", - __func__, - aw8695->haptic_audio.cnt, - aw8695->haptic_audio.ctr.cmd, - aw8695->haptic_audio.ctr.play, - aw8695->haptic_audio.ctr.wavseq, - aw8695->haptic_audio.ctr.loop, - aw8695->haptic_audio.ctr.gain); - mutex_unlock(&aw8695->haptic_audio.lock); - if(aw8695->haptic_audio.ctr.cmd == 0x01) { - if(aw8695->haptic_audio.ctr.play == 0x01) { - pr_info("%s: haptic_audio_play_start\n", __func__); - mutex_lock(&aw8695->lock); - aw8695_haptic_stop(aw8695); - - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); - - aw8695_haptic_set_wav_seq(aw8695, 0x00, - aw8695->haptic_audio.ctr.wavseq); - aw8695_haptic_set_wav_seq(aw8695, 0x01, 0x00); - - aw8695_haptic_set_wav_loop(aw8695, 0x00, - aw8695->haptic_audio.ctr.loop); - - aw8695_haptic_set_gain(aw8695, - aw8695->haptic_audio.ctr.gain); - - aw8695_haptic_start(aw8695); - mutex_unlock(&aw8695->lock); - } - mutex_lock(&aw8695->haptic_audio.lock); - memset(&aw8695->haptic_audio.data[aw8695->haptic_audio.cnt], - 0, sizeof(struct haptic_ctr)); - mutex_unlock(&aw8695->haptic_audio.lock); - } - - mutex_lock(&aw8695->haptic_audio.lock); - aw8695->haptic_audio.cnt ++; - if(aw8695->haptic_audio.data[aw8695->haptic_audio.cnt].cmd == 0) { - aw8695->haptic_audio.cnt = 0; - pr_debug("%s: haptic play buffer restart\n", __func__); - } - mutex_unlock(&aw8695->haptic_audio.lock); - -} - - - -/***************************************************** - * - * haptic cont - * - *****************************************************/ -static int aw8695_haptic_cont(struct aw8695 *aw8695) -{ - pr_debug("%s enter\n", __func__); - - mutex_lock(&aw8695->lock); - - - /* work mode */ - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_CONT_MODE); - - /* preset f0 */ - aw8695->f0_pre = aw8695->f0; - aw8695_haptic_set_f0_preset(aw8695); - - /* lpf */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, - AW8695_BIT_DATCTRL_FC_MASK, AW8695_BIT_DATCTRL_FC_1000HZ); - aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, - AW8695_BIT_DATCTRL_LPF_ENABLE_MASK, AW8695_BIT_DATCTRL_LPF_ENABLE); - - /* cont config */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_ZC_DETEC_MASK, AW8695_BIT_CONT_CTRL_ZC_DETEC_ENABLE); - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_WAIT_PERIOD_MASK, AW8695_BIT_CONT_CTRL_WAIT_1PERIOD); - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_MODE_MASK, AW8695_BIT_CONT_CTRL_BY_GO_SIGNAL); -#if AW8695_OPEN_PLAYBACK - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK, AW8695_BIT_CONT_CTRL_OPEN_PLAYBACK); -#else - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK, AW8695_BIT_CONT_CTRL_CLOSE_PLAYBACK); -#endif - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_F0_DETECT_MASK, AW8695_BIT_CONT_CTRL_F0_DETECT_DISABLE); - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_O2C_MASK, AW8695_BIT_CONT_CTRL_O2C_DISABLE); - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_AUTO_BRK_MASK, AW8695_BIT_CONT_CTRL_AUTO_BRK_ENABLE); - - /* TD time */ - aw8695_i2c_write(aw8695, AW8695_REG_TD_H, 0x00); - aw8695_i2c_write(aw8695, AW8695_REG_TD_L, 0x73); - aw8695_i2c_write(aw8695, AW8695_REG_TSET, 0x12); - - /* zero cross */ - aw8695_i2c_write(aw8695, AW8695_REG_ZC_THRSH_H, 0x0f); - aw8695_i2c_write(aw8695, AW8695_REG_ZC_THRSH_L, 0xf1); - - /* bemf */ - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_H, 0x10); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_L, 0x08); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_H, 0x03); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_L, 0xf8); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_NUM, 0x54); - aw8695_i2c_write(aw8695, AW8695_REG_TIME_NZC, 0x1f); - - /* f0 driver level */ - aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL, aw8695->f0_drv_lvl); - aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL_OV, 0x70); - - /* cont play go */ - aw8695_haptic_play_go(aw8695, true); - - mutex_unlock(&aw8695->lock); - - return 0; -} - -/***************************************************** - * - * haptic f0 cali - * - *****************************************************/ -static int aw8695_haptic_f0_calibration(struct aw8695 *aw8695) -{ - int ret = 0; - unsigned char i = 0; - unsigned char reg_val = 0; - unsigned char f0_pre_num = 0; - unsigned char f0_wait_num = 0; - unsigned char f0_repeat_num = 0; - unsigned char f0_trace_num = 0; - unsigned int t_f0_ms = 0; - unsigned int t_f0_trace_ms = 0; - unsigned int f0_cali_cnt = 50; - char f0_cali_lra = 0; - int f0_cali_step = 0; - int f0_dft_step = 0; - - pr_info("%s enter\n", __func__); - - mutex_lock(&aw8695->lock); - - aw8695->f0_pre = AW8695_HAPTIC_F0_PRE; - aw8695->f0 = aw8695->f0_pre; - aw8695->f0_drv_lvl = AW8695_HAPTIC_F0_DRV_LVL; - - /* f0 calibrate work mode */ - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_CONT_MODE); - - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK, AW8695_BIT_CONT_CTRL_OPEN_PLAYBACK); - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_F0_DETECT_MASK, AW8695_BIT_CONT_CTRL_F0_DETECT_ENABLE); - - /* LPF */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, - AW8695_BIT_DATCTRL_FC_MASK, AW8695_BIT_DATCTRL_FC_1000HZ); - aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, - AW8695_BIT_DATCTRL_LPF_ENABLE_MASK, AW8695_BIT_DATCTRL_LPF_ENABLE); - - /* LRA OSC Source */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_ANACTRL, - AW8695_BIT_ANACTRL_LRA_SRC_MASK, AW8695_BIT_ANACTRL_LRA_SRC_REG); - - /* preset f0 */ - aw8695_haptic_set_f0_preset(aw8695); - - /* beme config */ - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_H, 0x10); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_L, 0x08); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_H, 0x03); - aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_L, 0xf8); - - /* f0 driver level */ - aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL, aw8695->f0_drv_lvl); - - /* f0 trace parameter */ - f0_pre_num = 0x05; - f0_wait_num = 0x03; - f0_repeat_num = 0x02; - f0_trace_num = 0x0f; - aw8695_i2c_write(aw8695, AW8695_REG_NUM_F0_1, (f0_pre_num<<4)|(f0_wait_num<<0)); - aw8695_i2c_write(aw8695, AW8695_REG_NUM_F0_2, (f0_repeat_num<<0)); - aw8695_i2c_write(aw8695, AW8695_REG_NUM_F0_3, (f0_trace_num<<0)); - - /* clear aw8695 interrupt */ - ret = aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - - /* play go and start f0 calibration */ - aw8695_haptic_play_go(aw8695, true); - - /* f0 trace time */ - t_f0_ms = 1000*10/aw8695->f0_pre; - t_f0_trace_ms = t_f0_ms * (f0_pre_num + f0_wait_num + (f0_trace_num+f0_wait_num)*(f0_repeat_num-1)); - msleep(t_f0_trace_ms); - - for(i=0; if0-(int)aw8695->f0_pre)/((int)aw8695->f0_pre*24); - pr_debug("%s f0_cali_step=%d\n", __func__, f0_cali_step); - - /* get default cali step */ - aw8695_i2c_read(aw8695, AW8695_REG_TRIM_LRA, ®_val); - if(reg_val & 0x20) { - f0_dft_step = reg_val - 0x40; - } else { - f0_dft_step = reg_val; - } - pr_debug("%s f0_dft_step=%d\n", __func__, f0_dft_step); - - /* get new cali step */ - f0_cali_step += f0_dft_step; - pr_debug("%s f0_cali_step=%d\n", __func__, f0_cali_step); - - if(f0_cali_step > 31) { - f0_cali_step = 31; - } else if(f0_cali_step < -32) { - f0_cali_step = -32; - } - f0_cali_lra = (char)f0_cali_step; - pr_debug("%s f0_cali_lra=%d\n", __func__, f0_cali_lra); - - /* get cali step complement code*/ - if(f0_cali_lra < 0) { - f0_cali_lra = ~f0_cali_lra; - f0_cali_lra ++; - } - pr_debug("%s reg f0_cali_lra=%d\n", __func__, f0_cali_lra); - - /* update cali step */ - aw8695_i2c_write(aw8695, AW8695_REG_TRIM_LRA, (char)f0_cali_lra); - aw8695_i2c_read(aw8695, AW8695_REG_TRIM_LRA, ®_val); - pr_info("%s final trim_lra=0x%02x\n", __func__, reg_val); - } - - /* restore default work mode */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK, AW8695_BIT_CONT_CTRL_CLOSE_PLAYBACK); - aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, - AW8695_BIT_CONT_CTRL_F0_DETECT_MASK, AW8695_BIT_CONT_CTRL_F0_DETECT_DISABLE); - - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); - aw8695_haptic_stop(aw8695); - - mutex_unlock(&aw8695->lock); - - return ret; -} - -/***************************************************** - * - * haptic fops - * - *****************************************************/ -static int aw8695_file_open(struct inode *inode, struct file *file) -{ - if (!try_module_get(THIS_MODULE)) - return -ENODEV; - - file->private_data = (void*)g_aw8695; - - return 0; -} - -static int aw8695_file_release(struct inode *inode, struct file *file) -{ - file->private_data = (void*)NULL; - - module_put(THIS_MODULE); - - return 0; -} - -static long aw8695_file_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct aw8695 *aw8695 = (struct aw8695 *)file->private_data; - - int ret = 0; - - dev_info(aw8695->dev, "%s: cmd=0x%x, arg=0x%lx\n", - __func__, cmd, arg); - - mutex_lock(&aw8695->lock); - - if(_IOC_TYPE(cmd) != AW8695_HAPTIC_IOCTL_MAGIC) { - dev_err(aw8695->dev, "%s: cmd magic err\n", - __func__); - return -EINVAL; - } - - switch (cmd) { - default: - dev_err(aw8695->dev, "%s, unknown cmd\n", __func__); - break; - } - - mutex_unlock(&aw8695->lock); - - return ret; -} - -static ssize_t aw8695_file_read(struct file* filp, char* buff, size_t len, loff_t* offset) -{ - struct aw8695 *aw8695 = (struct aw8695 *)filp->private_data; - int ret = 0; - int i = 0; - unsigned char reg_val = 0; - unsigned char *pbuff = NULL; - - mutex_lock(&aw8695->lock); - - dev_info(aw8695->dev, "%s: len=%zu\n", __func__, len); - - switch(aw8695->fileops.cmd) - { - case AW8695_HAPTIC_CMD_READ_REG: - pbuff = (unsigned char *)kzalloc(len, GFP_KERNEL); - if(pbuff != NULL) { - for(i=0; ifileops.reg+i, ®_val); - pbuff[i] = reg_val; - } - for(i=0; idev, "%s: pbuff[%d]=0x%02x\n", - __func__, i, pbuff[i]); - } - ret = copy_to_user(buff, pbuff, len); - if(ret) { - dev_err(aw8695->dev, "%s: copy to user fail\n", __func__); - } - kfree(pbuff); - } else { - dev_err(aw8695->dev, "%s: alloc memory fail\n", __func__); - } - break; - default: - dev_err(aw8695->dev, "%s, unknown cmd %d \n", __func__, aw8695->fileops.cmd); - break; - } - - mutex_unlock(&aw8695->lock); - - - return len; -} - -static ssize_t aw8695_file_write(struct file* filp, const char* buff, size_t len, loff_t* off) -{ - struct aw8695 *aw8695 = (struct aw8695 *)filp->private_data; - int i = 0; - int ret = 0; - unsigned char *pbuff = NULL; - - pbuff = (unsigned char *)kzalloc(len, GFP_KERNEL); - if(pbuff == NULL) { - dev_err(aw8695->dev, "%s: alloc memory fail\n", __func__); - return len; - } - ret = copy_from_user(pbuff, buff, len); - if(ret) { - dev_err(aw8695->dev, "%s: copy from user fail\n", __func__); - return len; - } - - for(i=0; idev, "%s: pbuff[%d]=0x%02x\n", - __func__, i, pbuff[i]); - } - - mutex_lock(&aw8695->lock); - - aw8695->fileops.cmd = pbuff[0]; - - switch(aw8695->fileops.cmd) - { - case AW8695_HAPTIC_CMD_READ_REG: - if(len == 2) { - aw8695->fileops.reg = pbuff[1]; - } else { - dev_err(aw8695->dev, "%s: read cmd len %zu err\n", __func__, len); - } - break; - case AW8695_HAPTIC_CMD_WRITE_REG: - if(len > 2) { - for(i=0; idev, "%s: write reg0x%02x=0x%02x\n", - __func__, pbuff[1]+i, pbuff[i+2]); - aw8695_i2c_write(aw8695, pbuff[1]+i, pbuff[2+i]); - } - } else { - dev_err(aw8695->dev, "%s: write cmd len %zu err\n", __func__, len); - } - break; - default: - dev_err(aw8695->dev, "%s, unknown cmd %d \n", __func__, aw8695->fileops.cmd); - break; - } - - mutex_unlock(&aw8695->lock); - - if(pbuff != NULL) { - kfree(pbuff); - } - return len; -} - -static struct file_operations fops = -{ - .owner = THIS_MODULE, - .read = aw8695_file_read, - .write = aw8695_file_write, - .unlocked_ioctl = aw8695_file_unlocked_ioctl, - .open = aw8695_file_open, - .release = aw8695_file_release, -}; - -static struct miscdevice aw8695_haptic_misc = -{ - .minor = MISC_DYNAMIC_MINOR, - .name = AW8695_HAPTIC_NAME, - .fops = &fops, -}; - -static int aw8695_haptic_init(struct aw8695 *aw8695) -{ - int ret = 0; - unsigned char i = 0; - unsigned char reg_val = 0; - - pr_info("%s enter\n", __func__); - - ret = misc_register(&aw8695_haptic_misc); - if(ret) { - dev_err(aw8695->dev, "%s: misc fail: %d\n", __func__, ret); - return ret; - } - - /* haptic audio */ - aw8695->haptic_audio.delay_val = 20833; - aw8695->haptic_audio.timer_val = 20833; - - hrtimer_init(&aw8695->haptic_audio.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - aw8695->haptic_audio.timer.function = aw8695_haptic_audio_timer_func; - INIT_WORK(&aw8695->haptic_audio.work, aw8695_haptic_audio_work_routine); - - mutex_init(&aw8695->haptic_audio.lock); - - - /* haptic init */ - mutex_lock(&aw8695->lock); - - ret = aw8695_i2c_read(aw8695, AW8695_REG_WAVSEQ1, ®_val); - aw8695->index = reg_val & 0x7F; - ret = aw8695_i2c_read(aw8695, AW8695_REG_DATDBG, ®_val); - aw8695->gain = reg_val & 0xFF; - ret = aw8695_i2c_read(aw8695, AW8695_REG_BSTDBG4, ®_val); - aw8695->vmax = (reg_val>>0)&0x3F; - for(i=0; iseq[i] = reg_val; - } - - aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_STANDBY_MODE); - - aw8695_haptic_set_pwm(aw8695, AW8695_PWM_24K); - - aw8695_i2c_write(aw8695, AW8695_REG_BSTDBG1, 0x30); - aw8695_i2c_write(aw8695, AW8695_REG_BSTDBG2, 0xeb); - aw8695_i2c_write(aw8695, AW8695_REG_BSTDBG3, 0xd4); - aw8695_i2c_write(aw8695, AW8695_REG_TSET, 0x12); - aw8695_i2c_write(aw8695, AW8695_REG_R_SPARE, 0x68); - - aw8695_haptic_set_bst_peak_cur(aw8695, 0x01); - - mutex_unlock(&aw8695->lock); - - - /* f0 calibration */ - aw8695_haptic_f0_calibration(aw8695); - - return ret; -} - - - -/***************************************************** - * - * vibrator - * - *****************************************************/ -#ifdef TIMED_OUTPUT -static int aw8695_vibrator_get_time(struct timed_output_dev *dev) -{ - struct aw8695 *aw8695 = container_of(dev, struct aw8695, to_dev); - - if (hrtimer_active(&aw8695->timer)) { - ktime_t r = hrtimer_get_remaining(&aw8695->timer); - return ktime_to_ms(r); - } - - return 0; -} - -static void aw8695_vibrator_enable( struct timed_output_dev *dev, int value) -{ - struct aw8695 *aw8695 = container_of(dev, struct aw8695, to_dev); - - mutex_lock(&aw8695->lock); - - pr_debug("%s enter\n", __func__); - - aw8695_haptic_stop(aw8695); - - if (value > 0) { - aw8695_haptic_play_wav_seq(aw8695, value); - } - - mutex_unlock(&aw8695->lock); - - pr_debug("%s exit\n", __func__); -} - -#else -static enum led_brightness aw8695_haptic_brightness_get(struct led_classdev *cdev) -{ - struct aw8695 *aw8695 = - container_of(cdev, struct aw8695, cdev); - - return aw8695->amplitude; -} - -static void aw8695_haptic_brightness_set(struct led_classdev *cdev, - enum led_brightness level) -{ - struct aw8695 *aw8695 = - container_of(cdev, struct aw8695, cdev); - - aw8695->amplitude = level; - - mutex_lock(&aw8695->lock); - - aw8695_haptic_stop(aw8695); - if (aw8695->amplitude > 0) { - aw8695_haptic_play_wav_seq(aw8695, aw8695->amplitude); - } - - mutex_unlock(&aw8695->lock); - -} -#endif - -static ssize_t aw8695_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - - return snprintf(buf, PAGE_SIZE, "%d\n", aw8695->state); -} - -static ssize_t aw8695_state_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return count; -} - -static ssize_t aw8695_duration_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ktime_t time_rem; - s64 time_ms = 0; - - if (hrtimer_active(&aw8695->timer)) { - time_rem = hrtimer_get_remaining(&aw8695->timer); - time_ms = ktime_to_ms(time_rem); - } - - return snprintf(buf, PAGE_SIZE, "%lld\n", time_ms); -} - -static ssize_t aw8695_duration_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - /* setting 0 on duration is NOP for now */ - if (val <= 0) - return count; - - aw8695->duration = val; - - return count; -} - -static ssize_t aw8695_activate_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - - /* For now nothing to show */ - return snprintf(buf, PAGE_SIZE, "%d\n", aw8695->state); -} - -static ssize_t aw8695_activate_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0;; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - if (val != 0 && val != 1) - return count; - - pr_debug("%s: value=%d\n", __FUNCTION__, val); - - mutex_lock(&aw8695->lock); - hrtimer_cancel(&aw8695->timer); - - aw8695->state = val; - - if (aw8695->state) - { - /* clip value to max */ - val = aw8695->duration; - /* run ms timer */ - hrtimer_start(&aw8695->timer, - ktime_set(val / 1000, (val % 1000) * 1000000), - HRTIMER_MODE_REL); - } - mutex_unlock(&aw8695->lock); - schedule_work(&aw8695->vibrator_work); - - return count; -} - -static ssize_t aw8695_index_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned char reg_val = 0; - aw8695_i2c_read(aw8695, AW8695_REG_WAVSEQ1, ®_val); - aw8695->index = reg_val; - - return snprintf(buf, PAGE_SIZE, "%d\n", aw8695->index); -} - -static ssize_t aw8695_index_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - pr_debug("%s: value=%d\n", __FUNCTION__, val); - - mutex_lock(&aw8695->lock); - aw8695->index = val; - aw8695_haptic_set_repeat_wav_seq(aw8695, aw8695->index); - mutex_unlock(&aw8695->lock); - return count; -} - -static ssize_t aw8695_vmax_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - - return snprintf(buf, PAGE_SIZE, "0x%02x\n", aw8695->vmax); -} - -static ssize_t aw8695_vmax_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - pr_debug("%s: value=%d\n", __FUNCTION__, val); - - mutex_lock(&aw8695->lock); - aw8695->vmax = val; - aw8695_haptic_set_bst_vol(aw8695, aw8695->vmax); - mutex_unlock(&aw8695->lock); - return count; -} - -static ssize_t aw8695_gain_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - - return snprintf(buf, PAGE_SIZE, "0x%02x\n", aw8695->gain); -} - -static ssize_t aw8695_gain_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - pr_debug("%s: value=%d\n", __FUNCTION__, val); - - mutex_lock(&aw8695->lock); - aw8695->gain = val; - aw8695_haptic_set_gain(aw8695, aw8695->gain); - mutex_unlock(&aw8695->lock); - return count; -} - -static ssize_t aw8695_seq_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - size_t count = 0; - unsigned char i = 0; - unsigned char reg_val = 0; - - for(i=0; iseq[i] |= reg_val; - } - return count; -} - -static ssize_t aw8695_seq_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int databuf[2] = {0, 0}; - - if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { - pr_debug("%s: seq%d=0x%x\n", __FUNCTION__, databuf[0], databuf[1]); - mutex_lock(&aw8695->lock); - aw8695->seq[databuf[0]] = (unsigned char)databuf[1]; - aw8695_haptic_set_wav_seq(aw8695, (unsigned char)databuf[0], - aw8695->seq[databuf[0]]); - mutex_unlock(&aw8695->lock); - } - return count; -} - -static ssize_t aw8695_loop_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - size_t count = 0; - unsigned char i = 0; - unsigned char reg_val = 0; - - for(i=0; iloop[i*2+0] = (reg_val>>4)&0x0F; - aw8695->loop[i*2+1] = (reg_val>>0)&0x0F; - - count += snprintf(buf+count, PAGE_SIZE-count, - "seq%d loop: 0x%02x\n", i*2+1, aw8695->loop[i*2+0]); - count += snprintf(buf+count, PAGE_SIZE-count, - "seq%d loop: 0x%02x\n", i*2+2, aw8695->loop[i*2+1]); - } - return count; -} - -static ssize_t aw8695_loop_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int databuf[2] = {0, 0}; - - if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { - pr_debug("%s: seq%d loop=0x%x\n", __FUNCTION__, databuf[0], databuf[1]); - mutex_lock(&aw8695->lock); - aw8695->loop[databuf[0]] = (unsigned char)databuf[1]; - aw8695_haptic_set_wav_loop(aw8695, (unsigned char)databuf[0], - aw8695->loop[databuf[0]]); - mutex_unlock(&aw8695->lock); - } - - return count; -} - -static ssize_t aw8695_reg_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - unsigned char i = 0; - unsigned char reg_val = 0; - for(i = 0; i < AW8695_REG_MAX; i ++) { - if(!(aw8695_reg_access[i]®_RD_ACCESS)) - continue; - aw8695_i2c_read(aw8695, i, ®_val); - len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%02x=0x%02x \n", i, reg_val); - } - return len; -} - -static ssize_t aw8695_reg_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int databuf[2] = {0, 0}; - - if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { - aw8695_i2c_write(aw8695, (unsigned char)databuf[0], (unsigned char)databuf[1]); - } - - return count; -} - -static ssize_t aw8695_rtp_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - len += snprintf(buf+len, PAGE_SIZE-len, "rtp play: %d\n", aw8695->rtp_cnt); - - return len; -} - -static ssize_t aw8695_rtp_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - aw8695_haptic_stop(aw8695); - aw8695_haptic_set_rtp_aei(aw8695, false); - aw8695_interrupt_clear(aw8695); - if(val < (sizeof(aw8695_rtp_name)/AW8695_RTP_NAME_MAX)) { - aw8695->rtp_file_num = val; - if(val) { - schedule_work(&aw8695->rtp_work); - } - } else { - pr_err("%s: rtp_file_num 0x%02x over max value \n", __func__, aw8695->rtp_file_num); - } - - return count; -} - -static ssize_t aw8695_ram_update_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - //struct timed_output_dev *to_dev = dev_get_drvdata(dev); - //struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - //struct led_classdev *cdev = dev_get_drvdata(dev); - //struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - len += snprintf(buf+len, PAGE_SIZE-len, "sram update mode\n"); - return len; -} - -static ssize_t aw8695_ram_update_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - if(val) { - aw8695_ram_update(aw8695); - } - return count; -} - -static ssize_t aw8695_cali_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - aw8695_haptic_get_f0(aw8695); - len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 f0 = %d\n", aw8695->f0); - return len; -} - -static ssize_t aw8695_cali_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - if(val) { - aw8695_haptic_f0_calibration(aw8695); - } - return count; -} - -static ssize_t aw8695_cont_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - aw8695_haptic_get_f0(aw8695); - len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 f0 = %d\n", aw8695->f0); - return len; -} - -static ssize_t aw8695_cont_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int val = 0; - int rc = 0; - - rc = kstrtouint(buf, 0, &val); - if (rc < 0) - return rc; - - aw8695_haptic_stop(aw8695); - if(val) { - aw8695_haptic_cont(aw8695); - } - return count; -} - - -static ssize_t aw8695_haptic_audio_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", aw8695->haptic_audio.cnt); - return len; -} - -static ssize_t aw8695_haptic_audio_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int databuf[6] = {0}; - - if(6 == sscanf(buf, "%d %d %d %d %d %d", &databuf[0], &databuf[1], &databuf[2], - &databuf[3], &databuf[4], &databuf[5])) { - pr_debug("%s: cnt=%d, cmd=%d, play=%d, wavseq=%d, loop=%d, gain=%d\n", - __func__, databuf[0], databuf[1], databuf[2], databuf[3], - databuf[4], databuf[5]); - mutex_lock(&aw8695->haptic_audio.lock); - aw8695->haptic_audio.data[(unsigned char)databuf[0]].cmd = (unsigned char)databuf[1]; - aw8695->haptic_audio.data[(unsigned char)databuf[0]].play = (unsigned char)databuf[2]; - aw8695->haptic_audio.data[(unsigned char)databuf[0]].wavseq = (unsigned char)databuf[3]; - aw8695->haptic_audio.data[(unsigned char)databuf[0]].loop = (unsigned char)databuf[4]; - aw8695->haptic_audio.data[(unsigned char)databuf[0]].gain = (unsigned char)databuf[5]; - mutex_unlock(&aw8695->haptic_audio.lock); - - if(aw8695->haptic_audio.data[aw8695->haptic_audio.cnt].cmd == 0xff) { - pr_info("%s: haptic_audio stop\n", __func__); - if(hrtimer_active(&aw8695->haptic_audio.timer)) { - pr_info("%s: cancel haptic_audio_timer\n", __func__); - hrtimer_cancel(&aw8695->haptic_audio.timer); - aw8695->haptic_audio.cnt = 0; - aw8695_haptic_set_gain(aw8695, 0x80); - } - } else { - if(hrtimer_active(&aw8695->haptic_audio.timer)) { - } else { - pr_info("%s: start haptic_audio_timer\n", __func__); - hrtimer_start(&aw8695->haptic_audio.timer, - ktime_set(aw8695->haptic_audio.delay_val/1000000, - (aw8695->haptic_audio.delay_val%1000000)*1000), - HRTIMER_MODE_REL); - } - } - } - return count; -} - - -static ssize_t aw8695_haptic_audio_time_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - ssize_t len = 0; - len += snprintf(buf+len, PAGE_SIZE-len, "haptic_audio.delay_val=%dus\n", aw8695->haptic_audio.delay_val); - len += snprintf(buf+len, PAGE_SIZE-len, "haptic_audio.timer_val=%dus\n", aw8695->haptic_audio.timer_val); - return len; -} - -static ssize_t aw8695_haptic_audio_time_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ -#ifdef TIMED_OUTPUT - struct timed_output_dev *to_dev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); -#else - struct led_classdev *cdev = dev_get_drvdata(dev); - struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); -#endif - unsigned int databuf[2] = {0}; - - if(2 == sscanf(buf, "%d %d", &databuf[0], &databuf[1])) { - aw8695->haptic_audio.delay_val = databuf[0]; - aw8695->haptic_audio.timer_val = databuf[1]; - } - return count; -} - - -static DEVICE_ATTR(state, S_IWUSR | S_IRUGO, aw8695_state_show, aw8695_state_store); -static DEVICE_ATTR(duration, S_IWUSR | S_IRUGO, aw8695_duration_show, aw8695_duration_store); -static DEVICE_ATTR(activate, S_IWUSR | S_IRUGO, aw8695_activate_show, aw8695_activate_store); -static DEVICE_ATTR(index, S_IWUSR | S_IRUGO, aw8695_index_show, aw8695_index_store); -static DEVICE_ATTR(vmax, S_IWUSR | S_IRUGO, aw8695_vmax_show, aw8695_vmax_store); -static DEVICE_ATTR(gain, S_IWUSR | S_IRUGO, aw8695_gain_show, aw8695_gain_store); -static DEVICE_ATTR(seq, S_IWUSR | S_IRUGO, aw8695_seq_show, aw8695_seq_store); -static DEVICE_ATTR(loop, S_IWUSR | S_IRUGO, aw8695_loop_show, aw8695_loop_store); -static DEVICE_ATTR(register, S_IWUSR | S_IRUGO, aw8695_reg_show, aw8695_reg_store); -static DEVICE_ATTR(rtp, S_IWUSR | S_IRUGO, aw8695_rtp_show, aw8695_rtp_store); -static DEVICE_ATTR(ram_update, S_IWUSR | S_IRUGO, aw8695_ram_update_show, aw8695_ram_update_store); -static DEVICE_ATTR(cali, S_IWUSR | S_IRUGO, aw8695_cali_show, aw8695_cali_store); -static DEVICE_ATTR(cont, S_IWUSR | S_IRUGO, aw8695_cont_show, aw8695_cont_store); -static DEVICE_ATTR(haptic_audio, S_IWUSR | S_IRUGO, aw8695_haptic_audio_show, aw8695_haptic_audio_store); -static DEVICE_ATTR(haptic_audio_time, S_IWUSR | S_IRUGO, aw8695_haptic_audio_time_show, aw8695_haptic_audio_time_store); - - -static struct attribute *aw8695_vibrator_attributes[] = { - &dev_attr_state.attr, - &dev_attr_duration.attr, - &dev_attr_activate.attr, - &dev_attr_index.attr, - &dev_attr_vmax.attr, - &dev_attr_gain.attr, - &dev_attr_seq.attr, - &dev_attr_loop.attr, - &dev_attr_register.attr, - &dev_attr_rtp.attr, - &dev_attr_ram_update.attr, - &dev_attr_cali.attr, - &dev_attr_cont.attr, - &dev_attr_haptic_audio.attr, - &dev_attr_haptic_audio_time.attr, - NULL -}; - -static struct attribute_group aw8695_vibrator_attribute_group = { - .attrs = aw8695_vibrator_attributes -}; - -static enum hrtimer_restart aw8695_vibrator_timer_func(struct hrtimer *timer) -{ - struct aw8695 *aw8695 = container_of(timer, struct aw8695, timer); - - pr_debug("%s enter\n", __func__); - aw8695->state = 0; - schedule_work(&aw8695->vibrator_work); - - return HRTIMER_NORESTART; -} - -static void aw8695_vibrator_work_routine(struct work_struct *work) -{ - struct aw8695 *aw8695 = container_of(work, struct aw8695, vibrator_work); - - pr_debug("%s enter\n", __func__); -/* - mutex_lock(&aw8695->lock); - - if(aw8695->state) { - pr_info("%s play seq ture\n", __func__); - aw8695_haptic_play_repeat_seq(aw8695, true); - //aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); - //aw8695_haptic_set_repeat_seq(aw8695, 1); - //aw8695_haptic_start(aw8695); - } else { - pr_info("%s haptic stop\n", __func__); -*/ - aw8695_haptic_stop(aw8695); - if(aw8695->state) { - aw8695_haptic_cont(aw8695); - } -} - -static int aw8695_vibrator_init(struct aw8695 *aw8695) -{ - int ret = 0; - - pr_info("%s enter\n", __func__); - -#ifdef TIMED_OUTPUT - aw8695->to_dev.name = "vibrator"; - aw8695->to_dev.get_time = aw8695_vibrator_get_time; - aw8695->to_dev.enable = aw8695_vibrator_enable; - - ret = timed_output_dev_register(&(aw8695->to_dev)); - if ( ret < 0){ - dev_err(aw8695->dev, "%s: fail to create timed output dev\n", - __func__); - return ret; - } - ret = sysfs_create_group(&aw8695->to_dev.dev->kobj, &aw8695_vibrator_attribute_group); - if (ret < 0) { - dev_err(aw8695->dev, "%s error creating sysfs attr files\n", __func__); - return ret; - } -#else - aw8695->cdev.name = "vibrator"; - aw8695->cdev.brightness_get = aw8695_haptic_brightness_get; - aw8695->cdev.brightness_set = aw8695_haptic_brightness_set; - - ret = devm_led_classdev_register(&aw8695->i2c->dev, &aw8695->cdev); - if (ret < 0){ - dev_err(aw8695->dev, "%s: fail to create led dev\n", - __func__); - return ret; - } - ret = sysfs_create_group(&aw8695->cdev.dev->kobj, &aw8695_vibrator_attribute_group); - if (ret < 0) { - dev_err(aw8695->dev, "%s error creating sysfs attr files\n", __func__); - return ret; - } -#endif - hrtimer_init(&aw8695->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - aw8695->timer.function = aw8695_vibrator_timer_func; - INIT_WORK(&aw8695->vibrator_work, aw8695_vibrator_work_routine); - - INIT_WORK(&aw8695->rtp_work, aw8695_rtp_work_routine); - - mutex_init(&aw8695->lock); - - return 0; -} - - - - -/****************************************************** - * - * irq - * - ******************************************************/ -static void aw8695_interrupt_clear(struct aw8695 *aw8695) -{ - unsigned char reg_val = 0; - pr_debug("%s enter\n", __func__); - aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - pr_debug("%s: reg SYSINT=0x%x\n", __func__, reg_val); -} - -static void aw8695_interrupt_setup(struct aw8695 *aw8695) -{ - unsigned char reg_val = 0; - - pr_debug("%s enter\n", __func__); - - aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - pr_debug("%s: reg SYSINT=0x%x\n", __func__, reg_val); - - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_BSTERR_MASK, AW8695_BIT_SYSINTM_BSTERR_OFF); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_OV_MASK, AW8695_BIT_SYSINTM_OV_EN); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_UVLO_MASK, AW8695_BIT_SYSINTM_UVLO_EN); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_OCD_MASK, AW8695_BIT_SYSINTM_OCD_EN); - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, - AW8695_BIT_SYSINTM_OT_MASK, AW8695_BIT_SYSINTM_OT_EN); -} - -static irqreturn_t aw8695_irq(int irq, void *data) -{ - struct aw8695 *aw8695 = data; - unsigned char reg_val = 0; - unsigned char dbg_val = 0; - unsigned int buf_len = 0; - - pr_debug("%s enter\n", __func__); - - aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - pr_debug("%s: reg SYSINT=0x%x\n", __func__, reg_val); - aw8695_i2c_read(aw8695, AW8695_REG_DBGSTAT, &dbg_val); - pr_debug("%s: reg DBGSTAT=0x%x\n", __func__, dbg_val); - - if(reg_val & AW8695_BIT_SYSINT_OVI) { - pr_err("%s chip ov int error\n", __func__); - } - if(reg_val & AW8695_BIT_SYSINT_UVLI) { - pr_err("%s chip uvlo int error\n", __func__); - } - if(reg_val & AW8695_BIT_SYSINT_OCDI) { - pr_err("%s chip over current int error\n", __func__); - } - if(reg_val & AW8695_BIT_SYSINT_OTI) { - pr_err("%s chip over temperature int error\n", __func__); - } - if(reg_val & AW8695_BIT_SYSINT_DONEI) { - pr_info("%s chip playback done\n", __func__); - } - - if(reg_val & AW8695_BIT_SYSINT_FF_AEI) { - pr_debug("%s: aw8695 rtp fifo almost empty int\n", __func__); - if(aw8695->rtp_init) { - while((!aw8695_haptic_rtp_get_fifo_afi(aw8695)) && - (aw8695->play_mode == AW8695_HAPTIC_RTP_MODE)) { - pr_info("%s: aw8695 rtp mode fifo update, cnt=%d\n", - __func__, aw8695->rtp_cnt); - if((aw8695_rtp->len-aw8695->rtp_cnt) < (aw8695->ram.base_addr>>2)) { - buf_len = aw8695_rtp->len-aw8695->rtp_cnt; - } else { - buf_len = (aw8695->ram.base_addr>>2); - } - aw8695_i2c_writes(aw8695, AW8695_REG_RTP_DATA, - &aw8695_rtp->data[aw8695->rtp_cnt], buf_len); - aw8695->rtp_cnt += buf_len; - if(aw8695->rtp_cnt == aw8695_rtp->len) { - pr_info("%s: rtp update complete\n", __func__); - aw8695_haptic_set_rtp_aei(aw8695, false); - aw8695->rtp_cnt = 0; - aw8695->rtp_init = 0; - break; - } - } - } else { - pr_err("%s: aw8695 rtp init = %d, init error\n", __func__, aw8695->rtp_init); - } - } - - if(reg_val & AW8695_BIT_SYSINT_FF_AFI) { - pr_debug("%s: aw8695 rtp mode fifo full empty\n", __func__); - } - - if(aw8695->play_mode != AW8695_HAPTIC_RTP_MODE) { - aw8695_haptic_set_rtp_aei(aw8695, false); - } - - aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); - pr_debug("%s: reg SYSINT=0x%x\n", __func__, reg_val); - aw8695_i2c_read(aw8695, AW8695_REG_SYSST, ®_val); - pr_debug("%s: reg SYSST=0x%x\n", __func__, reg_val); - - pr_debug("%s exit\n", __func__); - - return IRQ_HANDLED; -} - -/***************************************************** - * - * device tree - * - *****************************************************/ -static int aw8695_parse_dt(struct device *dev, struct aw8695 *aw8695, - struct device_node *np) { - aw8695->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); - if (aw8695->reset_gpio < 0) { - dev_err(dev, "%s: no reset gpio provided, will not HW reset device\n", __func__); - return -1; - } else { - dev_info(dev, "%s: reset gpio provided ok\n", __func__); - } - aw8695->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0); - if (aw8695->irq_gpio < 0) { - dev_err(dev, "%s: no irq gpio provided.\n", __func__); - } else { - dev_info(dev, "%s: irq gpio provided ok.\n", __func__); - } - - return 0; -} - -static int aw8695_hw_reset(struct aw8695 *aw8695) -{ - pr_info("%s enter\n", __func__); - - if (aw8695 && gpio_is_valid(aw8695->reset_gpio)) { - gpio_set_value_cansleep(aw8695->reset_gpio, 0); - msleep(1); - gpio_set_value_cansleep(aw8695->reset_gpio, 1); - msleep(1); - } else { - dev_err(aw8695->dev, "%s: failed\n", __func__); - } - return 0; -} - - -/***************************************************** - * - * check chip id - * - *****************************************************/ -static int aw8695_read_chipid(struct aw8695 *aw8695) -{ - int ret = -1; - unsigned char cnt = 0; - unsigned char reg = 0; - - while(cnt < AW_READ_CHIPID_RETRIES) { - /* hardware reset */ - aw8695_hw_reset(aw8695); - - ret = aw8695_i2c_read(aw8695, AW8695_REG_ID, ®); - if (ret < 0) { - dev_err(aw8695->dev, "%s: failed to read register AW8695_REG_ID: %d\n", __func__, ret); - } - switch (reg) { - case 0x95: - pr_info("%s aw8695 detected\n", __func__); - aw8695->chipid = AW8695_ID; - //aw8695->flags |= AW8695_FLAG_SKIP_INTERRUPTS; - return 0; - default: - pr_info("%s unsupported device revision (0x%x)\n", __func__, reg ); - break; - } - cnt ++; - - msleep(AW_READ_CHIPID_RETRY_DELAY); - } - - return -EINVAL; -} - -/****************************************************** - * - * sys group attribute: reg - * - ******************************************************/ -static ssize_t aw8695_i2c_reg_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct aw8695 *aw8695 = dev_get_drvdata(dev); - - unsigned int databuf[2] = {0, 0}; - - if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { - aw8695_i2c_write(aw8695, (unsigned char)databuf[0], (unsigned char)databuf[1]); - } - - return count; -} - -static ssize_t aw8695_i2c_reg_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct aw8695 *aw8695 = dev_get_drvdata(dev); - ssize_t len = 0; - unsigned char i = 0; - unsigned char reg_val = 0; - for(i = 0; i < AW8695_REG_MAX; i ++) { - if(!(aw8695_reg_access[i]®_RD_ACCESS)) - continue; - aw8695_i2c_read(aw8695, i, ®_val); - len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%02x=0x%02x \n", i, reg_val); - } - return len; -} -static ssize_t aw8695_i2c_ram_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct aw8695 *aw8695 = dev_get_drvdata(dev); - - unsigned int databuf[1] = {0}; - - if(1 == sscanf(buf, "%x", &databuf[0])) { - if(1 == databuf[0]) { - aw8695_ram_update(aw8695); - } - } - - return count; -} - -static ssize_t aw8695_i2c_ram_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct aw8695 *aw8695 = dev_get_drvdata(dev); - ssize_t len = 0; - unsigned int i = 0; - unsigned char reg_val = 0; - - aw8695_haptic_stop(aw8695); - /* RAMINIT Enable */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_EN); - - aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRH, (unsigned char)(aw8695->ram.base_addr>>8)); - aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRL, (unsigned char)(aw8695->ram.base_addr&0x00ff)); - len += snprintf(buf+len, PAGE_SIZE-len, "aw8695_haptic_ram:\n"); - for(i=0; iram.len; i++) { - aw8695_i2c_read(aw8695, AW8695_REG_RAMDATA, ®_val); - len += snprintf(buf+len, PAGE_SIZE-len, "0x%02x,", reg_val); - } - len += snprintf(buf+len, PAGE_SIZE-len, "\n"); - /* RAMINIT Disable */ - aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, - AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_OFF); - - return len; -} - -static DEVICE_ATTR(reg, S_IWUSR | S_IRUGO, aw8695_i2c_reg_show, aw8695_i2c_reg_store); -static DEVICE_ATTR(ram, S_IWUSR | S_IRUGO, aw8695_i2c_ram_show, aw8695_i2c_ram_store); - -static struct attribute *aw8695_attributes[] = { - &dev_attr_reg.attr, - &dev_attr_ram.attr, - NULL -}; - -static struct attribute_group aw8695_attribute_group = { - .attrs = aw8695_attributes -}; - - -/****************************************************** - * - * i2c driver - * - ******************************************************/ -static int aw8695_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) -{ - struct aw8695 *aw8695; - struct device_node *np = i2c->dev.of_node; - int irq_flags = 0; - int ret = -1; - - pr_info("%s enter\n", __func__); - - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) { - dev_err(&i2c->dev, "check_functionality failed\n"); - return -EIO; - } - - aw8695 = devm_kzalloc(&i2c->dev, sizeof(struct aw8695), GFP_KERNEL); - if (aw8695 == NULL) - return -ENOMEM; - - aw8695->dev = &i2c->dev; - aw8695->i2c = i2c; - - i2c_set_clientdata(i2c, aw8695); - - /* aw8695 rst & int */ - if (np) { - ret = aw8695_parse_dt(&i2c->dev, aw8695, np); - if (ret) { - dev_err(&i2c->dev, "%s: failed to parse device tree node\n", __func__); - goto err; - } - } else { - aw8695->reset_gpio = -1; - aw8695->irq_gpio = -1; - } - - if (gpio_is_valid(aw8695->reset_gpio)) { - ret = devm_gpio_request_one(&i2c->dev, aw8695->reset_gpio, - GPIOF_OUT_INIT_LOW, "aw8695_rst"); - if (ret){ - dev_err(&i2c->dev, "%s: rst request failed\n", __func__); - goto err; - } - } - - if (gpio_is_valid(aw8695->irq_gpio)) { - ret = devm_gpio_request_one(&i2c->dev, aw8695->irq_gpio, - GPIOF_DIR_IN, "aw8695_int"); - if (ret){ - dev_err(&i2c->dev, "%s: int request failed\n", __func__); - goto err; - } - } - - /* aw8695 chip id */ - ret = aw8695_read_chipid(aw8695); - if (ret < 0) { - dev_err(&i2c->dev, "%s: aw8695_read_chipid failed ret=%d\n", __func__, ret); - goto err_id; - } - - /* aw8695 irq */ - if (gpio_is_valid(aw8695->irq_gpio) && - !(aw8695->flags & AW8695_FLAG_SKIP_INTERRUPTS)) { - /* register irq handler */ - aw8695_interrupt_setup(aw8695); - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - ret = devm_request_threaded_irq(&i2c->dev, - gpio_to_irq(aw8695->irq_gpio), - NULL, aw8695_irq, irq_flags, - "aw8695", aw8695); - if (ret != 0) { - dev_err(&i2c->dev, "%s: failed to request IRQ %d: %d\n", - __func__, gpio_to_irq(aw8695->irq_gpio), ret); - goto err_irq; - } - } else { - dev_info(&i2c->dev, "%s skipping IRQ registration\n", __func__); - /* disable feature support if gpio was invalid */ - aw8695->flags |= AW8695_FLAG_SKIP_INTERRUPTS; - } - - dev_set_drvdata(&i2c->dev, aw8695); - - ret = sysfs_create_group(&i2c->dev.kobj, &aw8695_attribute_group); - if (ret < 0) { - dev_info(&i2c->dev, "%s error creating sysfs attr files\n", __func__); - goto err_sysfs; - } - - g_aw8695 = aw8695; - - aw8695_haptic_softreset(aw8695); - - aw8695_vibrator_init(aw8695); - - aw8695_haptic_init(aw8695); - - aw8695_ram_init(aw8695); - - pr_info("%s probe completed successfully!\n", __func__); - - return 0; - -err_sysfs: - sysfs_remove_group(&i2c->dev.kobj, &aw8695_attribute_group); -err_irq: -err_id: -err: - return ret; -} - -static int aw8695_i2c_remove(struct i2c_client *i2c) -{ - struct aw8695 *aw8695 = i2c_get_clientdata(i2c); - - pr_info("%s enter\n", __func__); - - sysfs_remove_group(&i2c->dev.kobj, &aw8695_attribute_group); - - if (gpio_is_valid(aw8695->irq_gpio)) - devm_gpio_free(&i2c->dev, aw8695->irq_gpio); - if (gpio_is_valid(aw8695->reset_gpio)) - devm_gpio_free(&i2c->dev, aw8695->reset_gpio); - - return 0; -} - -static const struct i2c_device_id aw8695_i2c_id[] = { - { AW8695_I2C_NAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, aw8695_i2c_id); - -static struct of_device_id aw8695_dt_match[] = { - { .compatible = "awinic,aw8695_haptic" }, - { }, -}; - -static struct i2c_driver aw8695_i2c_driver = { - .driver = { - .name = AW8695_I2C_NAME, - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(aw8695_dt_match), - }, - .probe = aw8695_i2c_probe, - .remove = aw8695_i2c_remove, - .id_table = aw8695_i2c_id, -}; - - -static int __init aw8695_i2c_init(void) -{ - int ret = 0; - - pr_info("aw8695 driver version %s\n", AW8695_VERSION); - - ret = i2c_add_driver(&aw8695_i2c_driver); - if(ret){ - pr_err("fail to add aw8695 device into i2c\n"); - return ret; - } - - return 0; -} -//late_initcall(aw8695_i2c_init); -module_init(aw8695_i2c_init); - - -static void __exit aw8695_i2c_exit(void) -{ - i2c_del_driver(&aw8695_i2c_driver); -} -module_exit(aw8695_i2c_exit); - - -MODULE_DESCRIPTION("AW8695 Haptic Driver"); -MODULE_LICENSE("GPL v2"); +/* + * aw8695.c aw8695 haptic module + * + * Version: v1.2.4 + * + * Copyright (c) 2018 AWINIC Technology CO., LTD + * + * Author: Nick Li + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "aw8695.h" +#include "aw8695_reg.h" +#include "aw8695_config.h" + +/****************************************************** + * + * Marco + * + ******************************************************/ +#define AW8695_I2C_NAME "aw8695_haptic" +#define AW8695_HAPTIC_NAME "aw8695_haptic" + +#define AW8695_VERSION "v1.2.4" + + +#define AWINIC_RAM_UPDATE_DELAY + +#define AW_I2C_RETRIES 2 +#define AW_I2C_RETRY_DELAY 2 +#define AW_READ_CHIPID_RETRIES 5 +#define AW_READ_CHIPID_RETRY_DELAY 2 + +#define AW8695_MAX_DSP_START_TRY_COUNT 10 + + + +#define AW8695_MAX_FIRMWARE_LOAD_CNT 20 + +/****************************************************** + * + * variable + * + ******************************************************/ +#define AW8695_RTP_NAME_MAX 64 +static char *aw8695_ram_name = "aw8695_haptic.bin"; +static char aw8695_rtp_name[][AW8695_RTP_NAME_MAX] = { + {"aw8695_rtp.bin"}, + {"aw8695_rtp_lighthouse.bin"}, + {"aw8695_rtp_silk.bin"}, +}; + +struct aw8695_container *aw8695_rtp; +struct aw8695 *g_aw8695; + +/****************************************************** + * + * functions + * + ******************************************************/ +static void aw8695_interrupt_clear(struct aw8695 *aw8695); +static int aw8695_haptic_trig_enable_config(struct aw8695 *aw8695); + + + /****************************************************** + * + * aw8695 i2c write/read + * + ******************************************************/ +static int aw8695_i2c_write(struct aw8695 *aw8695, + unsigned char reg_addr, unsigned char reg_data) +{ + int ret = -1; + unsigned char cnt = 0; + + while(cnt < AW_I2C_RETRIES) { + ret = i2c_smbus_write_byte_data(aw8695->i2c, reg_addr, reg_data); + if(ret < 0) { + pr_err("%s: i2c_write cnt=%d error=%d\n", __func__, cnt, ret); + } else { + break; + } + cnt ++; + msleep(AW_I2C_RETRY_DELAY); + } + + return ret; +} + +static int aw8695_i2c_read(struct aw8695 *aw8695, + unsigned char reg_addr, unsigned char *reg_data) +{ + int ret = -1; + unsigned char cnt = 0; + + while(cnt < AW_I2C_RETRIES) { + ret = i2c_smbus_read_byte_data(aw8695->i2c, reg_addr); + if(ret < 0) { + pr_err("%s: i2c_read cnt=%d error=%d\n", __func__, cnt, ret); + } else { + *reg_data = ret; + break; + } + cnt ++; + msleep(AW_I2C_RETRY_DELAY); + } + + return ret; +} + +static int aw8695_i2c_write_bits(struct aw8695 *aw8695, + unsigned char reg_addr, unsigned int mask, unsigned char reg_data) +{ + unsigned char reg_val = 0; + + aw8695_i2c_read(aw8695, reg_addr, ®_val); + reg_val &= mask; + reg_val |= reg_data; + aw8695_i2c_write(aw8695, reg_addr, reg_val); + + return 0; +} + +static int aw8695_i2c_writes(struct aw8695 *aw8695, + unsigned char reg_addr, unsigned char *buf, unsigned int len) +{ + int ret = -1; + unsigned char *data; + + data = kmalloc(len+1, GFP_KERNEL); + if (data == NULL) { + pr_err("%s: can not allocate memory\n", __func__); + return -ENOMEM; + } + + data[0] = reg_addr; + memcpy(&data[1], buf, len); + + ret = i2c_master_send(aw8695->i2c, data, len+1); + if (ret < 0) { + pr_err("%s: i2c master send error\n", __func__); + } + + kfree(data); + + return ret; +} + +/***************************************************** + * + * ram update + * + *****************************************************/ +static void aw8695_rtp_loaded(const struct firmware *cont, void *context) +{ + struct aw8695 *aw8695 = context; + pr_info("%s enter\n", __func__); + + if (!cont) { + pr_err("%s: failed to read %s\n", __func__, aw8695_rtp_name[aw8695->rtp_file_num]); + release_firmware(cont); + return; + } + + pr_info("%s: loaded %s - size: %zu\n", __func__, aw8695_rtp_name[aw8695->rtp_file_num], + cont ? cont->size : 0); + + /* aw8695 rtp update */ + aw8695_rtp = kzalloc(cont->size+sizeof(int), GFP_KERNEL); + if (!aw8695_rtp) { + release_firmware(cont); + pr_err("%s: Error allocating memory\n", __func__); + return; + } + aw8695_rtp->len = cont->size; + pr_info("%s: rtp size = %d\n", __func__, aw8695_rtp->len); + memcpy(aw8695_rtp->data, cont->data, cont->size); + release_firmware(cont); + + aw8695->rtp_init = 1; + pr_info("%s: rtp update complete\n", __func__); +} + +static int aw8695_rtp_update(struct aw8695 *aw8695) +{ + pr_info("%s enter\n", __func__); + + return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + aw8695_rtp_name[aw8695->rtp_file_num], aw8695->dev, GFP_KERNEL, + aw8695, aw8695_rtp_loaded); +} + + + static void aw8695_container_update(struct aw8695 *aw8695, + struct aw8695_container *aw8695_cont) +{ + int i = 0; + unsigned int shift = 0; + + pr_info("%s enter\n", __func__); + + mutex_lock(&aw8695->lock); + + aw8695->ram.baseaddr_shift = 2; + aw8695->ram.ram_shift = 4; + + /* RAMINIT Enable */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_EN); + + /* base addr */ + shift = aw8695->ram.baseaddr_shift; + aw8695->ram.base_addr = (unsigned int)((aw8695_cont->data[0+shift]<<8) | + (aw8695_cont->data[1+shift])); + pr_info("%s: base_addr=0x%4x\n", __func__, aw8695->ram.base_addr); + + aw8695_i2c_write(aw8695, AW8695_REG_BASE_ADDRH, aw8695_cont->data[0+shift]); + aw8695_i2c_write(aw8695, AW8695_REG_BASE_ADDRL, aw8695_cont->data[1+shift]); + + aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AEH, + (unsigned char)((aw8695->ram.base_addr>>2)>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AEL, + (unsigned char)((aw8695->ram.base_addr>>2)&0x00FF)); + aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AFH, + (unsigned char)((aw8695->ram.base_addr-(aw8695->ram.base_addr>>2))>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_FIFO_AFL, + (unsigned char)((aw8695->ram.base_addr-(aw8695->ram.base_addr>>2))&0x00FF)); + + /* ram */ + shift = aw8695->ram.baseaddr_shift; + aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRH, aw8695_cont->data[0+shift]); + aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRL, aw8695_cont->data[1+shift]); + shift = aw8695->ram.ram_shift; + for(i=shift; ilen; i++) { + aw8695_i2c_write(aw8695, AW8695_REG_RAMDATA, aw8695_cont->data[i]); + } + +#if 0 + /* ram check */ + shift = aw8695->ram.baseaddr_shift; + aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRH, aw8695_cont->data[0+shift]); + aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRL, aw8695_cont->data[1+shift]); + shift = aw8695->ram.ram_shift; + for(i=shift; ilen; i++) { + aw8695_i2c_read(aw8695, AW8695_REG_RAMDATA, ®_val); + if(reg_val != aw8695_cont->data[i]) { + pr_err("%s: ram check error addr=0x%04x, file_data=0x%02x, ram_data=0x%02x\n", + __func__, i, aw8695_cont->data[i], reg_val); + return; + } + } +#endif + + /* RAMINIT Disable */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_OFF); + + mutex_unlock(&aw8695->lock); + + pr_info("%s exit\n", __func__); +} + + +static void aw8695_ram_loaded(const struct firmware *cont, void *context) +{ + struct aw8695 *aw8695 = context; + struct aw8695_container *aw8695_fw; + int i = 0; + unsigned short check_sum = 0; + + pr_info("%s enter\n", __func__); + + if (!cont) { + pr_err("%s: failed to read %s\n", __func__, aw8695_ram_name); + release_firmware(cont); + return; + } + + pr_info("%s: loaded %s - size: %zu\n", __func__, aw8695_ram_name, + cont ? cont->size : 0); +/* + for(i=0; isize; i++) { + pr_info("%s: addr:0x%04x, data:0x%02x\n", __func__, i, *(cont->data+i)); + } +*/ + + /* check sum */ + for(i=2; isize; i++) { + check_sum += cont->data[i]; + } + if(check_sum != (unsigned short)((cont->data[0]<<8)|(cont->data[1]))) { + pr_err("%s: check sum err: check_sum=0x%04x\n", __func__, check_sum); + return; + } else { + pr_info("%s: check sum pass : 0x%04x\n", __func__, check_sum); + aw8695->ram.check_sum = check_sum; + } + + /* aw8695 ram update */ + aw8695_fw = kzalloc(cont->size+sizeof(int), GFP_KERNEL); + if (!aw8695_fw) { + release_firmware(cont); + pr_err("%s: Error allocating memory\n", __func__); + return; + } + aw8695_fw->len = cont->size; + memcpy(aw8695_fw->data, cont->data, cont->size); + release_firmware(cont); + + aw8695_container_update(aw8695, aw8695_fw); + + aw8695->ram.len = aw8695_fw->len; + + kfree(aw8695_fw); + + aw8695->ram_init = 1; + pr_info("%s: fw update complete\n", __func__); + + aw8695_haptic_trig_enable_config(aw8695); + + aw8695_rtp_update(aw8695); +} + +static int aw8695_ram_update(struct aw8695 *aw8695) +{ + aw8695->ram_init = 0; + aw8695->rtp_init = 0; + return request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + aw8695_ram_name, aw8695->dev, GFP_KERNEL, + aw8695, aw8695_ram_loaded); +} + +#ifdef AWINIC_RAM_UPDATE_DELAY +static void aw8695_ram_work_routine(struct work_struct *work) +{ + struct aw8695 *aw8695 = container_of(work, struct aw8695, ram_work.work); + + pr_info("%s enter\n", __func__); + + aw8695_ram_update(aw8695); + +} +#endif + +static int aw8695_ram_init(struct aw8695 *aw8695) +{ +#ifdef AWINIC_RAM_UPDATE_DELAY + int ram_timer_val = 5000; + INIT_DELAYED_WORK(&aw8695->ram_work, aw8695_ram_work_routine); + schedule_delayed_work(&aw8695->ram_work, msecs_to_jiffies(ram_timer_val)); +#else + aw8695_ram_update(aw8695); +#endif + return 0; +} + + + +/***************************************************** + * + * haptic control + * + *****************************************************/ +static int aw8695_haptic_softreset(struct aw8695 *aw8695) +{ + pr_debug("%s enter\n", __func__); + + aw8695_i2c_write(aw8695, AW8695_REG_ID, 0xAA); + msleep(1); + return 0; +} + +static int aw8695_haptic_active(struct aw8695 *aw8695) +{ + pr_debug("%s enter\n", __func__); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_WORK_MODE_MASK, AW8695_BIT_SYSCTRL_ACTIVE); + aw8695_interrupt_clear(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_UVLO_MASK, AW8695_BIT_SYSINTM_UVLO_EN); + return 0; +} + +static int aw8695_haptic_play_mode(struct aw8695 *aw8695, unsigned char play_mode) +{ + pr_debug("%s enter\n", __func__); + + switch(play_mode) { + case AW8695_HAPTIC_STANDBY_MODE: + aw8695->play_mode = AW8695_HAPTIC_STANDBY_MODE; + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_UVLO_MASK, AW8695_BIT_SYSINTM_UVLO_OFF); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_WORK_MODE_MASK, AW8695_BIT_SYSCTRL_STANDBY); + break; + case AW8695_HAPTIC_RAM_MODE: + aw8695->play_mode = AW8695_HAPTIC_RAM_MODE; + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RAM); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + aw8695_haptic_active(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_DISABLE); + } + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + msleep(3); + break; + case AW8695_HAPTIC_RAM_LOOP_MODE: + aw8695->play_mode = AW8695_HAPTIC_RAM_LOOP_MODE; + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RAM); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + aw8695_haptic_active(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_DISABLE); + } + msleep(3); + break; + case AW8695_HAPTIC_RTP_MODE: + aw8695->play_mode = AW8695_HAPTIC_RTP_MODE; + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RTP); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + aw8695_haptic_active(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_DISABLE); + } + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + msleep(3); + break; + case AW8695_HAPTIC_TRIG_MODE: + aw8695->play_mode = AW8695_HAPTIC_TRIG_MODE; + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_RAM); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + aw8695_haptic_active(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_DISABLE); + } + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + msleep(3); + break; + case AW8695_HAPTIC_CONT_MODE: + aw8695->play_mode = AW8695_HAPTIC_CONT_MODE; + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_PLAY_MODE_MASK, AW8695_BIT_SYSCTRL_PLAY_MODE_CONT); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_ENABLE); + } + aw8695_haptic_active(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + if(aw8695->auto_boost) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_RAM_MASK, AW8695_BIT_BST_AUTO_BST_RAM_DISABLE); + } + msleep(3); + break; + default: + dev_err(aw8695->dev, "%s: play mode %d err", + __func__, play_mode); + break; + } + return 0; +} + +static int aw8695_haptic_play_go(struct aw8695 *aw8695, bool flag) +{ + pr_debug("%s enter\n", __func__); + + if(flag == true) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_GO, + AW8695_BIT_GO_MASK, AW8695_BIT_GO_ENABLE); + } else { + aw8695_i2c_write_bits(aw8695, AW8695_REG_GO, + AW8695_BIT_GO_MASK, AW8695_BIT_GO_DISABLE); + } + return 0; +} + +static int aw8695_haptic_stop_delay(struct aw8695 *aw8695) +{ + unsigned char reg_val = 0; + unsigned int cnt = 100; + + while(cnt--) { + aw8695_i2c_read(aw8695, AW8695_REG_GLB_STATE, ®_val); + if((reg_val&0x0f) == 0x00) { + return 0; + } + msleep(2); + pr_info("%s wait for standby, reg glb_state=0x%02x\n", + __func__, reg_val); + } + pr_err("%s do not enter standby automatically\n", __func__); + + return 0; +} + +static int aw8695_haptic_stop(struct aw8695 *aw8695) +{ + pr_debug("%s enter\n", __func__); + + aw8695_haptic_play_go(aw8695, false); + aw8695_haptic_stop_delay(aw8695); + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_STANDBY_MODE); + + return 0; +} + +static int aw8695_haptic_start(struct aw8695 *aw8695) +{ + pr_debug("%s enter\n", __func__); + + aw8695_haptic_play_go(aw8695, true); + + return 0; +} + +static int aw8695_haptic_set_wav_seq(struct aw8695 *aw8695, + unsigned char wav, unsigned char seq) +{ + aw8695_i2c_write(aw8695, AW8695_REG_WAVSEQ1+wav, + seq); + return 0; +} + +static int aw8695_haptic_set_wav_loop(struct aw8695 *aw8695, + unsigned char wav, unsigned char loop) +{ + unsigned char tmp = 0; + + if(wav%2) { + tmp = loop<<0; + aw8695_i2c_write_bits(aw8695, AW8695_REG_WAVLOOP1+(wav/2), + AW8695_BIT_WAVLOOP_SEQNP1_MASK, tmp); + } else { + tmp = loop<<4; + aw8695_i2c_write_bits(aw8695, AW8695_REG_WAVLOOP1+(wav/2), + AW8695_BIT_WAVLOOP_SEQN_MASK, tmp); + } + + return 0; +} +/* +static int aw8695_haptic_set_main_loop(struct aw8695 *aw8695, + unsigned char loop) +{ + aw8695_i2c_write(aw8695, AW8695_REG_MAIN_LOOP, loop); + return 0; +} +*/ + +static int aw8695_haptic_set_repeat_wav_seq(struct aw8695 *aw8695, unsigned char seq) +{ + aw8695_haptic_set_wav_seq(aw8695, 0x00, seq); + aw8695_haptic_set_wav_loop(aw8695, 0x00, AW8695_BIT_WAVLOOP_INIFINITELY); + + return 0; +} + + +static int aw8695_haptic_set_bst_vol(struct aw8695 *aw8695, unsigned char bst_vol) +{ + if(bst_vol & 0xe0) { + bst_vol = 0x1f; + } + aw8695_i2c_write_bits(aw8695, AW8695_REG_BSTDBG4, + AW8695_BIT_BSTDBG4_BSTVOL_MASK, (bst_vol<<1)); + return 0; +} + +static int aw8695_haptic_set_bst_peak_cur(struct aw8695 *aw8695, unsigned char peak_cur) +{ + peak_cur &= AW8695_BSTCFG_PEAKCUR_LIMIT; + aw8695_i2c_write_bits(aw8695, AW8695_REG_BSTCFG, + AW8695_BIT_BSTCFG_PEAKCUR_MASK, peak_cur); + return 0; +} + +static int aw8695_haptic_set_gain(struct aw8695 *aw8695, unsigned char gain) +{ + aw8695_i2c_write(aw8695, AW8695_REG_DATDBG, gain); + return 0; +} + +static int aw8695_haptic_set_pwm(struct aw8695 *aw8695, unsigned char mode) +{ + switch(mode) { + case AW8695_PWM_48K: + aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMDBG, + AW8695_BIT_PWMDBG_PWM_MODE_MASK, AW8695_BIT_PWMDBG_PWM_48K); + break; + case AW8695_PWM_24K: + aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMDBG, + AW8695_BIT_PWMDBG_PWM_MODE_MASK, AW8695_BIT_PWMDBG_PWM_24K); + break; + case AW8695_PWM_12K: + aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMDBG, + AW8695_BIT_PWMDBG_PWM_MODE_MASK, AW8695_BIT_PWMDBG_PWM_12K); + break; + default: + break; + } + return 0; +} + +static int aw8695_haptic_play_wav_seq(struct aw8695 *aw8695, unsigned char flag) +{ + pr_debug("%s enter\n", __func__); + + //aw8695_haptic_stop(aw8695); + if(flag) { + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); + aw8695_haptic_start(aw8695); + } + return 0; +} + +static int aw8695_haptic_play_repeat_seq(struct aw8695 *aw8695, unsigned char flag) +{ + pr_debug("%s enter\n", __func__); + //aw8695_haptic_stop(aw8695); + if(flag) { + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_LOOP_MODE); + aw8695_haptic_start(aw8695); + } + + return 0; +} + +static int aw8695_haptic_swicth_motorprotect_config(struct aw8695 *aw8695, unsigned char addr, unsigned char val) +{ + pr_debug("%s enter\n", __func__); + if(addr == 1) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_PROTECT_MASK, AW8695_BIT_DETCTRL_PROTECT_SHUTDOWN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMPRC, + AW8695_BIT_PWMPRC_PRC_MASK, AW8695_BIT_PWMPRC_PRC_ENABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_PRLVL, + AW8695_BIT_PRLVL_PR_MASK, AW8695_BIT_PRLVL_PR_ENABLE); + } else if (addr == 0) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_PROTECT_MASK, AW8695_BIT_DETCTRL_PROTECT_NO_ACTION); + aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMPRC, + AW8695_BIT_PWMPRC_PRC_MASK, AW8695_BIT_PWMPRC_PRC_DISABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_PRLVL, + AW8695_BIT_PRLVL_PR_MASK, AW8695_BIT_PRLVL_PR_DISABLE); + } else if (addr == 0x2d){ + aw8695_i2c_write_bits(aw8695, AW8695_REG_PWMPRC, + AW8695_BIT_PWMPRC_PRCTIME_MASK, val); + }else if (addr == 0x3e){ + aw8695_i2c_write_bits(aw8695, AW8695_REG_PRLVL, + AW8695_BIT_PRLVL_PRLVL_MASK, val); + }else if (addr == 0x3f){ + aw8695_i2c_write_bits(aw8695, AW8695_REG_PRTIME, + AW8695_BIT_PRTIME_PRTIME_MASK, val); + } else{ + /*nothing to do;*/ + } + return 0; +} + +static int aw8695_haptic_trig_default_level(struct aw8695 *aw8695) +{ + pr_debug("%s enter\n", __func__); + aw8695_i2c_write_bits(aw8695, AW8695_REG_TRG_CFG1, + AW8695_BIT_TRGCFG1_TRG1_POLAR_MASK, AW8695_TRG1_DEFAULT_POLAR); + aw8695_i2c_write_bits(aw8695, AW8695_REG_TRG_CFG1, + AW8695_BIT_TRGCFG1_TRG2_POLAR_MASK, AW8695_TRG2_DEFAULT_POLAR); + aw8695_i2c_write_bits(aw8695, AW8695_REG_TRG_CFG1, + AW8695_BIT_TRGCFG1_TRG3_POLAR_MASK, AW8695_TRG3_DEFAULT_POLAR); + + return 0; +} + +static int aw8695_haptic_trig_enable_config(struct aw8695 *aw8695) +{ + pr_debug("%s enter\n", __func__); + aw8695_i2c_write_bits(aw8695, AW8695_REG_TRG_CFG2, + AW8695_BIT_TRGCFG2_TRG1_ENABLE_MASK, AW8695_TRG1_DEFAULT_ENABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_TRG_CFG2, + AW8695_BIT_TRGCFG2_TRG2_ENABLE_MASK, AW8695_TRG2_DEFAULT_ENABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_TRG_CFG2, + AW8695_BIT_TRGCFG2_TRG3_ENABLE_MASK, AW8695_TRG3_DEFAULT_ENABLE); + + return 0; +} + + +static int aw8695_haptic_auto_boost_config(struct aw8695 *aw8695, unsigned char flag) +{ + aw8695->auto_boost = flag; + if(flag) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_AUTOSW_MASK, AW8695_BIT_BST_AUTO_BST_AUTOMATIC_BOOST); + } else { + aw8695_i2c_write_bits(aw8695, AW8695_REG_BST_AUTO, + AW8695_BIT_BST_AUTO_BST_AUTOSW_MASK, AW8695_BIT_BST_AUTO_BST_MANUAL_BOOST); + } + return 0; +} + +static int aw8695_haptic_vbat_mode(struct aw8695 *aw8695, unsigned char flag) +{ + if(flag == AW8695_HAPTIC_VBAT_HW_COMP_MODE) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_ADCTEST, + AW8695_BIT_ADCTEST_VBAT_MODE_MASK, AW8695_BIT_ADCTEST_VBAT_HW_COMP); + } else { + aw8695_i2c_write_bits(aw8695, AW8695_REG_ADCTEST, + AW8695_BIT_ADCTEST_VBAT_MODE_MASK, AW8695_BIT_ADCTEST_VBAT_SW_COMP); + } + return 0; +} + + +static int aw8695_haptic_set_f0_preset(struct aw8695 *aw8695) +{ + unsigned int f0_reg = 0; + + pr_debug("%s enter\n", __func__); + + f0_reg = 1000000000/(aw8695->f0_pre*AW8695_HAPTIC_F0_COEFF); + aw8695_i2c_write(aw8695, AW8695_REG_F_PRE_H, (unsigned char)((f0_reg>>8)&0xff)); + aw8695_i2c_write(aw8695, AW8695_REG_F_PRE_L, (unsigned char)((f0_reg>>0)&0xff)); + + return 0; +} + +static int aw8695_haptic_read_f0(struct aw8695 *aw8695) +{ + int ret = 0; + unsigned char reg_val = 0; + unsigned int f0_reg = 0; + unsigned long f0_tmp = 0; + + pr_debug("%s enter\n", __func__); + + ret = aw8695_i2c_read(aw8695, AW8695_REG_F_LRA_F0_H, ®_val); + f0_reg = (reg_val<<8); + ret = aw8695_i2c_read(aw8695, AW8695_REG_F_LRA_F0_L, ®_val); + f0_reg |= (reg_val<<0); + f0_tmp = 1000000000/(f0_reg*AW8695_HAPTIC_F0_COEFF); + aw8695->f0 = (unsigned int)f0_tmp; + pr_info("%s f0=%d\n", __func__, aw8695->f0); + + return 0; +} + +static int aw8695_haptic_read_cont_f0(struct aw8695 *aw8695) +{ + int ret = 0; + unsigned char reg_val = 0; + unsigned int f0_reg = 0; + unsigned long f0_tmp = 0; + + pr_debug("%s enter\n", __func__); + + ret = aw8695_i2c_read(aw8695, AW8695_REG_F_LRA_CONT_H, ®_val); + f0_reg = (reg_val<<8); + ret = aw8695_i2c_read(aw8695, AW8695_REG_F_LRA_CONT_L, ®_val); + f0_reg |= (reg_val<<0); + f0_tmp = 1000000000/(f0_reg*AW8695_HAPTIC_F0_COEFF); + aw8695->cont_f0 = (unsigned int)f0_tmp; + pr_info("%s f0=%d\n", __func__, aw8695->cont_f0); + + return 0; +} + +static int aw8695_haptic_read_beme(struct aw8695 *aw8695) +{ + int ret = 0; + unsigned char reg_val = 0; + + ret = aw8695_i2c_read(aw8695, AW8695_REG_WAIT_VOL_MP, ®_val); + aw8695->max_pos_beme = (reg_val<<0); + ret = aw8695_i2c_read(aw8695, AW8695_REG_WAIT_VOL_MN, ®_val); + aw8695->max_neg_beme = (reg_val<<0); + + pr_info("%s max_pos_beme=%d\n", __func__, aw8695->max_pos_beme); + pr_info("%s max_neg_beme=%d\n", __func__, aw8695->max_neg_beme); + + return 0; +} + + + +static void aw8695_haptic_set_rtp_aei(struct aw8695 *aw8695, bool flag) +{ + if(flag) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_FF_AE_MASK, AW8695_BIT_SYSINTM_FF_AE_EN); + } else { + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_FF_AE_MASK, AW8695_BIT_SYSINTM_FF_AE_OFF); + } +} +/* +static void aw8695_haptic_set_rtp_afi(struct aw8695 *aw8695, bool flag) +{ + if(flag) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_FF_AF_MASK, AW8695_BIT_SYSINTM_FF_AF_EN); + } else { + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_FF_AF_MASK, AW8695_BIT_SYSINTM_FF_AF_OFF); + } +} +*/ +/* +static unsigned char aw8695_haptic_rtp_get_fifo_aei(struct aw8695 *aw8695) +{ + unsigned char ret; + unsigned char reg_val; + + aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + reg_val &= AW8695_BIT_SYSINT_FF_AEI; + ret = reg_val>>4; + + return ret; +} +*/ + +static unsigned char aw8695_haptic_rtp_get_fifo_afi(struct aw8695 *aw8695) +{ + unsigned char ret = 0; + unsigned char reg_val = 0; + + aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + reg_val &= AW8695_BIT_SYSINT_FF_AFI; + ret = reg_val>>3; + + return ret; +} + +static int aw8695_haptic_rtp_init(struct aw8695 *aw8695) +{ + unsigned int buf_len = 0; + + pr_info("%s enter\n", __func__); + + aw8695->rtp_cnt = 0; + + while((!aw8695_haptic_rtp_get_fifo_afi(aw8695)) && + (aw8695->play_mode == AW8695_HAPTIC_RTP_MODE)) { + pr_info("%s rtp cnt = %d\n", __func__, aw8695->rtp_cnt); + if((aw8695_rtp->len-aw8695->rtp_cnt) < (aw8695->ram.base_addr>>2)) { + buf_len = aw8695_rtp->len-aw8695->rtp_cnt; + } else { + buf_len = (aw8695->ram.base_addr>>2); + } + aw8695_i2c_writes(aw8695, AW8695_REG_RTP_DATA, + &aw8695_rtp->data[aw8695->rtp_cnt], buf_len); + aw8695->rtp_cnt += buf_len; + if(aw8695->rtp_cnt == aw8695_rtp->len) { + pr_info("%s: rtp update complete\n", __func__); + aw8695->rtp_cnt = 0; + return 0; + } + } + + if(aw8695->play_mode == AW8695_HAPTIC_RTP_MODE) { + aw8695_haptic_set_rtp_aei(aw8695, true); + } + + pr_info("%s exit\n", __func__); + + return 0; +} + +static void aw8695_rtp_work_routine(struct work_struct *work) +{ + const struct firmware *rtp_file; + int ret = -1; + struct aw8695 *aw8695 = container_of(work, struct aw8695, rtp_work); + + pr_info("%s enter\n", __func__); + + /* fw loaded */ + ret = request_firmware(&rtp_file, + aw8695_rtp_name[aw8695->rtp_file_num], + aw8695->dev); + if(ret < 0) + { + pr_err("%s: failed to read %s\n", __func__, + aw8695_rtp_name[aw8695->rtp_file_num]); + return ; + } + aw8695->rtp_init = 0; + kfree(aw8695_rtp); + aw8695_rtp = kzalloc(rtp_file->size+sizeof(int), GFP_KERNEL); + if (!aw8695_rtp) { + release_firmware(rtp_file); + pr_err("%s: error allocating memory\n", __func__); + return; + } + aw8695_rtp->len = rtp_file->size; + pr_info("%s: rtp file [%s] size = %d\n", __func__, + aw8695_rtp_name[aw8695->rtp_file_num], aw8695_rtp->len); + memcpy(aw8695_rtp->data, rtp_file->data, rtp_file->size); + release_firmware(rtp_file); + + aw8695->rtp_init = 1; + + /* rtp mode config */ + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RTP_MODE); + + /* haptic start */ + aw8695_haptic_start(aw8695); + + aw8695_haptic_rtp_init(aw8695); +} + + +/***************************************************** + * + * haptic - audio + * + *****************************************************/ +static enum hrtimer_restart aw8695_haptic_audio_timer_func(struct hrtimer *timer) +{ + struct aw8695 *aw8695 = container_of(timer, struct aw8695, haptic_audio.timer); + + pr_debug("%s enter\n", __func__); + schedule_work(&aw8695->haptic_audio.work); + + hrtimer_start(&aw8695->haptic_audio.timer, + ktime_set(aw8695->haptic_audio.timer_val/1000000, + (aw8695->haptic_audio.timer_val%1000000)*1000), + HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} + +static void aw8695_haptic_audio_work_routine(struct work_struct *work) +{ + struct aw8695 *aw8695 = container_of(work, struct aw8695, haptic_audio.work); + + pr_debug("%s enter\n", __func__); + + mutex_lock(&aw8695->haptic_audio.lock); + memcpy(&aw8695->haptic_audio.ctr, + &aw8695->haptic_audio.data[aw8695->haptic_audio.cnt], + sizeof(struct haptic_ctr)); + pr_debug("%s: cnt=%d, cmd=%d, play=%d, wavseq=%d, loop=%d, gain=%d\n", + __func__, + aw8695->haptic_audio.cnt, + aw8695->haptic_audio.ctr.cmd, + aw8695->haptic_audio.ctr.play, + aw8695->haptic_audio.ctr.wavseq, + aw8695->haptic_audio.ctr.loop, + aw8695->haptic_audio.ctr.gain); + mutex_unlock(&aw8695->haptic_audio.lock); + if(aw8695->haptic_audio.ctr.cmd == 0x01) { + if(aw8695->haptic_audio.ctr.play == 0x01) { + pr_info("%s: haptic_audio_play_start\n", __func__); + mutex_lock(&aw8695->lock); + aw8695_haptic_stop(aw8695); + + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); + + aw8695_haptic_set_wav_seq(aw8695, 0x00, + aw8695->haptic_audio.ctr.wavseq); + aw8695_haptic_set_wav_seq(aw8695, 0x01, 0x00); + + aw8695_haptic_set_wav_loop(aw8695, 0x00, + aw8695->haptic_audio.ctr.loop); + + aw8695_haptic_set_gain(aw8695, + aw8695->haptic_audio.ctr.gain); + + aw8695_haptic_start(aw8695); + mutex_unlock(&aw8695->lock); + } + mutex_lock(&aw8695->haptic_audio.lock); + memset(&aw8695->haptic_audio.data[aw8695->haptic_audio.cnt], + 0, sizeof(struct haptic_ctr)); + mutex_unlock(&aw8695->haptic_audio.lock); + } + + mutex_lock(&aw8695->haptic_audio.lock); + aw8695->haptic_audio.cnt ++; + if(aw8695->haptic_audio.data[aw8695->haptic_audio.cnt].cmd == 0) { + aw8695->haptic_audio.cnt = 0; + pr_debug("%s: haptic play buffer restart\n", __func__); + } + mutex_unlock(&aw8695->haptic_audio.lock); + +} + + +/***************************************************** + * + * haptic cont + * + *****************************************************/ +static int aw8695_haptic_cont(struct aw8695 *aw8695) +{ + pr_info("%s enter\n", __func__); + + /* work mode */ + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_CONT_MODE); + + /* preset f0 */ + aw8695->f0_pre = aw8695->f0; + aw8695_haptic_set_f0_preset(aw8695); + + /* lpf */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, + AW8695_BIT_DATCTRL_FC_MASK, AW8695_BIT_DATCTRL_FC_1000HZ); + aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, + AW8695_BIT_DATCTRL_LPF_ENABLE_MASK, AW8695_BIT_DATCTRL_LPF_ENABLE); + + /* cont config */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_ZC_DETEC_MASK, AW8695_BIT_CONT_CTRL_ZC_DETEC_ENABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_WAIT_PERIOD_MASK, AW8695_BIT_CONT_CTRL_WAIT_1PERIOD); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_MODE_MASK, AW8695_BIT_CONT_CTRL_BY_GO_SIGNAL); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK, AW8695_CONT_PLAYBACK_MODE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_F0_DETECT_MASK, AW8695_BIT_CONT_CTRL_F0_DETECT_DISABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_O2C_MASK, AW8695_BIT_CONT_CTRL_O2C_DISABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_AUTO_BRK_MASK, AW8695_BIT_CONT_CTRL_AUTO_BRK_ENABLE); + + /* TD time */ + aw8695_i2c_write(aw8695, AW8695_REG_TD_H, (unsigned char)(aw8695->cont_td>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_TD_L, (unsigned char)(aw8695->cont_td>>0)); + aw8695_i2c_write(aw8695, AW8695_REG_TSET, 0x12); + + /* zero cross */ + aw8695_i2c_write(aw8695, AW8695_REG_ZC_THRSH_H, (unsigned char)(aw8695->cont_zc_thr>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_ZC_THRSH_L, (unsigned char)(aw8695->cont_zc_thr>>0)); + + /* bemf */ + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_H, 0x10); + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_L, 0x08); + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_H, 0x03); + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_L, 0xf8); + aw8695_i2c_write_bits(aw8695, AW8695_REG_BEMF_NUM, + AW8695_BIT_BEMF_NUM_BRK_MASK, aw8695->cont_num_brk); + aw8695_i2c_write(aw8695, AW8695_REG_TIME_NZC, 0x23); // 35*171us=5.985ms + + /* f0 driver level */ + aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL, aw8695->cont_drv_lvl); + aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL_OV, aw8695->cont_drv_lvl_ov); + + /* cont play go */ + aw8695_haptic_play_go(aw8695, true); + + return 0; +} + +/***************************************************** + * + * haptic f0 cali + * + *****************************************************/ +static int aw8695_haptic_get_f0(struct aw8695 *aw8695) +{ + int ret = 0; + unsigned char i = 0; + unsigned char reg_val = 0; + unsigned char f0_pre_num = 0; + unsigned char f0_wait_num = 0; + unsigned char f0_repeat_num = 0; + unsigned char f0_trace_num = 0; + unsigned int t_f0_ms = 0; + unsigned int t_f0_trace_ms = 0; + unsigned int f0_cali_cnt = 50; + + pr_info("%s enter\n", __func__); + + aw8695->f0 = aw8695->f0_pre; + + /* f0 calibrate work mode */ + aw8695_haptic_stop(aw8695); + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_CONT_MODE); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK, AW8695_BIT_CONT_CTRL_OPEN_PLAYBACK); + aw8695_i2c_write_bits(aw8695, AW8695_REG_CONT_CTRL, + AW8695_BIT_CONT_CTRL_F0_DETECT_MASK, AW8695_BIT_CONT_CTRL_F0_DETECT_ENABLE); + + /* LPF */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, + AW8695_BIT_DATCTRL_FC_MASK, AW8695_BIT_DATCTRL_FC_1000HZ); + aw8695_i2c_write_bits(aw8695, AW8695_REG_DATCTRL, + AW8695_BIT_DATCTRL_LPF_ENABLE_MASK, AW8695_BIT_DATCTRL_LPF_ENABLE); + + /* LRA OSC Source */ + if(aw8695->f0_cali_flag == AW8695_HAPTIC_CALI_F0) { + aw8695_i2c_write_bits(aw8695, AW8695_REG_ANACTRL, + AW8695_BIT_ANACTRL_LRA_SRC_MASK, AW8695_BIT_ANACTRL_LRA_SRC_REG); + } else { + aw8695_i2c_write_bits(aw8695, AW8695_REG_ANACTRL, + AW8695_BIT_ANACTRL_LRA_SRC_MASK, AW8695_BIT_ANACTRL_LRA_SRC_EFUSE); + } + + /* preset f0 */ + aw8695_haptic_set_f0_preset(aw8695); + + /* beme config */ + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_H, 0x10); + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHH_L, 0x08); + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_H, 0x03); + aw8695_i2c_write(aw8695, AW8695_REG_BEMF_VTHL_L, 0xf8); + + /* f0 driver level */ + aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL, aw8695->cont_drv_lvl); + + /* f0 trace parameter */ + f0_pre_num = 0x05; + f0_wait_num = 0x03; + f0_repeat_num = 0x02; + f0_trace_num = 0x0f; + aw8695_i2c_write(aw8695, AW8695_REG_NUM_F0_1, (f0_pre_num<<4)|(f0_wait_num<<0)); + aw8695_i2c_write(aw8695, AW8695_REG_NUM_F0_2, (f0_repeat_num<<0)); + aw8695_i2c_write(aw8695, AW8695_REG_NUM_F0_3, (f0_trace_num<<0)); + + /* clear aw8695 interrupt */ + ret = aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + + /* play go and start f0 calibration */ + aw8695_haptic_play_go(aw8695, true); + + /* f0 trace time */ + t_f0_ms = 1000*10/aw8695->f0_pre; + t_f0_trace_ms = t_f0_ms * (f0_pre_num + f0_wait_num + (f0_trace_num+f0_wait_num)*(f0_repeat_num-1)); + msleep(t_f0_trace_ms); + + for(i=0; if0_cali_flag = AW8695_HAPTIC_CALI_F0; + + if(aw8695_haptic_get_f0(aw8695)) { + pr_err("%s get f0 error, user defafult f0\n", __func__); + } else { + /* max and min limit */ + f0_limit = aw8695->f0; + if(aw8695->f0*100 < AW8695_HAPTIC_F0_PRE*(100-AW8695_HAPTIC_F0_CALI_PERCEN)) { + f0_limit = AW8695_HAPTIC_F0_PRE*(100-AW8695_HAPTIC_F0_CALI_PERCEN)/100; + } + if(aw8695->f0*100 > AW8695_HAPTIC_F0_PRE*(100+AW8695_HAPTIC_F0_CALI_PERCEN)) { + f0_limit = AW8695_HAPTIC_F0_PRE*(100+AW8695_HAPTIC_F0_CALI_PERCEN)/100; + } + + /* calculate cali step */ + f0_cali_step = 10000*((int)f0_limit-(int)aw8695->f0_pre)/((int)f0_limit*25); + pr_debug("%s f0_cali_step=%d\n", __func__, f0_cali_step); + + /* get default cali step */ + aw8695_i2c_read(aw8695, AW8695_REG_TRIM_LRA, ®_val); + if(reg_val & 0x20) { + f0_dft_step = reg_val - 0x40; + } else { + f0_dft_step = reg_val; + } + pr_debug("%s f0_dft_step=%d\n", __func__, f0_dft_step); + + /* get new cali step */ + f0_cali_step += f0_dft_step; + pr_debug("%s f0_cali_step=%d\n", __func__, f0_cali_step); + + if(f0_cali_step > 31) { + f0_cali_step = 31; + } else if(f0_cali_step < -32) { + f0_cali_step = -32; + } + f0_cali_lra = (char)f0_cali_step; + pr_debug("%s f0_cali_lra=%d\n", __func__, f0_cali_lra); + + /* get cali step complement code*/ + if(f0_cali_lra < 0) { + f0_cali_lra += 0x40; + } + pr_debug("%s reg f0_cali_lra=%d\n", __func__, f0_cali_lra); + + /* update cali step */ + aw8695_i2c_write(aw8695, AW8695_REG_TRIM_LRA, (char)f0_cali_lra); + aw8695_i2c_read(aw8695, AW8695_REG_TRIM_LRA, ®_val); + pr_info("%s final trim_lra=0x%02x\n", __func__, reg_val); + } + + /* restore default work mode */ + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_STANDBY_MODE); + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_RAM_MODE); + aw8695_haptic_stop(aw8695); + + return ret; +} + +/***************************************************** + * + * haptic fops + * + *****************************************************/ +static int aw8695_file_open(struct inode *inode, struct file *file) +{ + if (!try_module_get(THIS_MODULE)) + return -ENODEV; + + file->private_data = (void*)g_aw8695; + + return 0; +} + +static int aw8695_file_release(struct inode *inode, struct file *file) +{ + file->private_data = (void*)NULL; + + module_put(THIS_MODULE); + + return 0; +} + +static long aw8695_file_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct aw8695 *aw8695 = (struct aw8695 *)file->private_data; + + int ret = 0; + + dev_info(aw8695->dev, "%s: cmd=0x%x, arg=0x%lx\n", + __func__, cmd, arg); + + mutex_lock(&aw8695->lock); + + if(_IOC_TYPE(cmd) != AW8695_HAPTIC_IOCTL_MAGIC) { + dev_err(aw8695->dev, "%s: cmd magic err\n", + __func__); + return -EINVAL; + } + + switch (cmd) { + default: + dev_err(aw8695->dev, "%s, unknown cmd\n", __func__); + break; + } + + mutex_unlock(&aw8695->lock); + + return ret; +} + +static ssize_t aw8695_file_read(struct file* filp, char* buff, size_t len, loff_t* offset) +{ + struct aw8695 *aw8695 = (struct aw8695 *)filp->private_data; + int ret = 0; + int i = 0; + unsigned char reg_val = 0; + unsigned char *pbuff = NULL; + + mutex_lock(&aw8695->lock); + + dev_info(aw8695->dev, "%s: len=%zu\n", __func__, len); + + switch(aw8695->fileops.cmd) + { + case AW8695_HAPTIC_CMD_READ_REG: + pbuff = (unsigned char *)kzalloc(len, GFP_KERNEL); + if(pbuff != NULL) { + for(i=0; ifileops.reg+i, ®_val); + pbuff[i] = reg_val; + } + for(i=0; idev, "%s: pbuff[%d]=0x%02x\n", + __func__, i, pbuff[i]); + } + ret = copy_to_user(buff, pbuff, len); + if(ret) { + dev_err(aw8695->dev, "%s: copy to user fail\n", __func__); + } + kfree(pbuff); + } else { + dev_err(aw8695->dev, "%s: alloc memory fail\n", __func__); + } + break; + default: + dev_err(aw8695->dev, "%s, unknown cmd %d \n", __func__, aw8695->fileops.cmd); + break; + } + + mutex_unlock(&aw8695->lock); + + + return len; +} + +static ssize_t aw8695_file_write(struct file* filp, const char* buff, size_t len, loff_t* off) +{ + struct aw8695 *aw8695 = (struct aw8695 *)filp->private_data; + int i = 0; + int ret = 0; + unsigned char *pbuff = NULL; + + pbuff = (unsigned char *)kzalloc(len, GFP_KERNEL); + if(pbuff == NULL) { + dev_err(aw8695->dev, "%s: alloc memory fail\n", __func__); + return len; + } + ret = copy_from_user(pbuff, buff, len); + if(ret) { + dev_err(aw8695->dev, "%s: copy from user fail\n", __func__); + return len; + } + + for(i=0; idev, "%s: pbuff[%d]=0x%02x\n", + __func__, i, pbuff[i]); + } + + mutex_lock(&aw8695->lock); + + aw8695->fileops.cmd = pbuff[0]; + + switch(aw8695->fileops.cmd) + { + case AW8695_HAPTIC_CMD_READ_REG: + if(len == 2) { + aw8695->fileops.reg = pbuff[1]; + } else { + dev_err(aw8695->dev, "%s: read cmd len %zu err\n", __func__, len); + } + break; + case AW8695_HAPTIC_CMD_WRITE_REG: + if(len > 2) { + for(i=0; idev, "%s: write reg0x%02x=0x%02x\n", + __func__, pbuff[1]+i, pbuff[i+2]); + aw8695_i2c_write(aw8695, pbuff[1]+i, pbuff[2+i]); + } + } else { + dev_err(aw8695->dev, "%s: write cmd len %zu err\n", __func__, len); + } + break; + default: + dev_err(aw8695->dev, "%s, unknown cmd %d \n", __func__, aw8695->fileops.cmd); + break; + } + + mutex_unlock(&aw8695->lock); + + if(pbuff != NULL) { + kfree(pbuff); + } + return len; +} + +static struct file_operations fops = +{ + .owner = THIS_MODULE, + .read = aw8695_file_read, + .write = aw8695_file_write, + .unlocked_ioctl = aw8695_file_unlocked_ioctl, + .open = aw8695_file_open, + .release = aw8695_file_release, +}; + +static struct miscdevice aw8695_haptic_misc = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = AW8695_HAPTIC_NAME, + .fops = &fops, +}; + +static int aw8695_haptic_init(struct aw8695 *aw8695) +{ + int ret = 0; + unsigned char i = 0; + unsigned char reg_val = 0; + + pr_info("%s enter\n", __func__); + + ret = misc_register(&aw8695_haptic_misc); + if(ret) { + dev_err(aw8695->dev, "%s: misc fail: %d\n", __func__, ret); + return ret; + } + + /* haptic audio */ + aw8695->haptic_audio.delay_val = 20833; + aw8695->haptic_audio.timer_val = 20833; + + hrtimer_init(&aw8695->haptic_audio.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + aw8695->haptic_audio.timer.function = aw8695_haptic_audio_timer_func; + INIT_WORK(&aw8695->haptic_audio.work, aw8695_haptic_audio_work_routine); + + mutex_init(&aw8695->haptic_audio.lock); + + + /* haptic init */ + mutex_lock(&aw8695->lock); + + aw8695->activate_mode = AW8695_HAPTIC_ACTIVATE_RAM_MODE; + + ret = aw8695_i2c_read(aw8695, AW8695_REG_WAVSEQ1, ®_val); + aw8695->index = reg_val & 0x7F; + ret = aw8695_i2c_read(aw8695, AW8695_REG_DATDBG, ®_val); + aw8695->gain = reg_val & 0xFF; + ret = aw8695_i2c_read(aw8695, AW8695_REG_BSTDBG4, ®_val); + aw8695->vmax = (reg_val>>1)&0x1F; + for(i=0; iseq[i] = reg_val; + } + + aw8695_haptic_play_mode(aw8695, AW8695_HAPTIC_STANDBY_MODE); + + aw8695_haptic_set_pwm(aw8695, AW8695_PWM_24K); + + aw8695_i2c_write(aw8695, AW8695_REG_BSTDBG1, 0x30); + aw8695_i2c_write(aw8695, AW8695_REG_BSTDBG2, 0xeb); + aw8695_i2c_write(aw8695, AW8695_REG_BSTDBG3, 0xd4); + aw8695_i2c_write(aw8695, AW8695_REG_TSET, 0x12); + aw8695_i2c_write(aw8695, AW8695_REG_R_SPARE, 0x68); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_ANADBG, + AW8695_BIT_ANADBG_IOC_MASK, AW8695_BIT_ANADBG_IOC_4P65A); + + aw8695_haptic_set_bst_peak_cur(aw8695, AW8695_DEFAULT_PEAKCUR); + aw8695_haptic_swicth_motorprotect_config(aw8695, 0x00, 0x00); + aw8695_haptic_auto_boost_config(aw8695, false); + aw8695_haptic_trig_default_level(aw8695); + aw8695_haptic_vbat_mode(aw8695, AW8695_HAPTIC_VBAT_HW_COMP_MODE); + + mutex_unlock(&aw8695->lock); + + + /* f0 calibration */ + mutex_lock(&aw8695->lock); + aw8695->f0_pre = AW8695_HAPTIC_F0_PRE; + aw8695->cont_drv_lvl = AW8695_HAPTIC_CONT_DRV_LVL; + aw8695->cont_drv_lvl_ov = AW8695_HAPTIC_CONT_DRV_LVL_OV; + aw8695->cont_td = AW8695_HAPTIC_CONT_TD; + aw8695->cont_zc_thr = AW8695_HAPTIC_CONT_ZC_THR; + aw8695->cont_num_brk = AW8695_HAPTIC_CONT_NUM_BRK; + aw8695_haptic_f0_calibration(aw8695); + mutex_unlock(&aw8695->lock); + + return ret; +} + + + +/***************************************************** + * + * vibrator + * + *****************************************************/ +#ifdef TIMED_OUTPUT +static int aw8695_vibrator_get_time(struct timed_output_dev *dev) +{ + struct aw8695 *aw8695 = container_of(dev, struct aw8695, to_dev); + + if (hrtimer_active(&aw8695->timer)) { + ktime_t r = hrtimer_get_remaining(&aw8695->timer); + return ktime_to_ms(r); + } + + return 0; +} + +static void aw8695_vibrator_enable( struct timed_output_dev *dev, int value) +{ + struct aw8695 *aw8695 = container_of(dev, struct aw8695, to_dev); + + mutex_lock(&aw8695->lock); + + pr_debug("%s enter\n", __func__); + + aw8695_haptic_stop(aw8695); + + if (value > 0) { + aw8695_haptic_play_wav_seq(aw8695, value); + } + + mutex_unlock(&aw8695->lock); + + pr_debug("%s exit\n", __func__); +} + +#else +static enum led_brightness aw8695_haptic_brightness_get(struct led_classdev *cdev) +{ + struct aw8695 *aw8695 = + container_of(cdev, struct aw8695, cdev); + + return aw8695->amplitude; +} + +static void aw8695_haptic_brightness_set(struct led_classdev *cdev, + enum led_brightness level) +{ + struct aw8695 *aw8695 = + container_of(cdev, struct aw8695, cdev); + + aw8695->amplitude = level; + + mutex_lock(&aw8695->lock); + + aw8695_haptic_stop(aw8695); + if (aw8695->amplitude > 0) { + aw8695_haptic_play_wav_seq(aw8695, aw8695->amplitude); + } + + mutex_unlock(&aw8695->lock); + +} +#endif + +static ssize_t aw8695_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + + return snprintf(buf, PAGE_SIZE, "%d\n", aw8695->state); +} + +static ssize_t aw8695_state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + return count; +} + +static ssize_t aw8695_duration_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ktime_t time_rem; + s64 time_ms = 0; + + if (hrtimer_active(&aw8695->timer)) { + time_rem = hrtimer_get_remaining(&aw8695->timer); + time_ms = ktime_to_ms(time_rem); + } + + return snprintf(buf, PAGE_SIZE, "%lld\n", time_ms); +} + +static ssize_t aw8695_duration_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + /* setting 0 on duration is NOP for now */ + if (val <= 0) + return count; + + aw8695->duration = val; + + return count; +} + +static ssize_t aw8695_activate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + + /* For now nothing to show */ + return snprintf(buf, PAGE_SIZE, "%d\n", aw8695->state); +} + +static ssize_t aw8695_activate_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0;; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + if (val != 0 && val != 1) + return count; + + pr_debug("%s: value=%d\n", __FUNCTION__, val); + + mutex_lock(&aw8695->lock); + hrtimer_cancel(&aw8695->timer); + + aw8695->state = val; + if (aw8695->duration > 100) { + aw8695_haptic_set_repeat_wav_seq(aw8695, AW8695_LONG_RAM); + } else if (aw8695->duration < 100) { + aw8695_haptic_set_wav_seq(aw8695, 0x00, AW8695_SHORT_RAM_100_UP); + } + + if (aw8695->state) + { + /* clip value to max */ + val = aw8695->duration; + /* run ms timer */ + hrtimer_start(&aw8695->timer, + ktime_set(val / 1000, (val % 1000) * 1000000), + HRTIMER_MODE_REL); + } + mutex_unlock(&aw8695->lock); + schedule_work(&aw8695->vibrator_work); + + return count; +} + +static ssize_t aw8695_activate_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + + return snprintf(buf, PAGE_SIZE, "activate_mode=%d\n", aw8695->activate_mode); +} + +static ssize_t aw8695_activate_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + mutex_lock(&aw8695->lock); + aw8695->activate_mode = val; + mutex_unlock(&aw8695->lock); + return count; +} + +static ssize_t aw8695_index_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned char reg_val = 0; + aw8695_i2c_read(aw8695, AW8695_REG_WAVSEQ1, ®_val); + aw8695->index = reg_val; + + return snprintf(buf, PAGE_SIZE, "%d\n", aw8695->index); +} + +static ssize_t aw8695_index_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + pr_debug("%s: value=%d\n", __FUNCTION__, val); + + mutex_lock(&aw8695->lock); + aw8695->index = val; + aw8695_haptic_set_repeat_wav_seq(aw8695, aw8695->index); + mutex_unlock(&aw8695->lock); + return count; +} + +static ssize_t aw8695_vmax_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + + return snprintf(buf, PAGE_SIZE, "0x%02x\n", aw8695->vmax); +} + +static ssize_t aw8695_vmax_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + pr_debug("%s: value=%d\n", __FUNCTION__, val); + + mutex_lock(&aw8695->lock); + aw8695->vmax = val; + aw8695_haptic_set_bst_vol(aw8695, aw8695->vmax); + mutex_unlock(&aw8695->lock); + return count; +} + +static ssize_t aw8695_gain_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + + return snprintf(buf, PAGE_SIZE, "0x%02x\n", aw8695->gain); +} + +static ssize_t aw8695_gain_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + pr_debug("%s: value=%d\n", __FUNCTION__, val); + + mutex_lock(&aw8695->lock); + aw8695->gain = val; + aw8695_haptic_set_gain(aw8695, aw8695->gain); + mutex_unlock(&aw8695->lock); + return count; +} + +static ssize_t aw8695_seq_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + size_t count = 0; + unsigned char i = 0; + unsigned char reg_val = 0; + + for(i=0; iseq[i] |= reg_val; + } + return count; +} + +static ssize_t aw8695_seq_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[2] = {0, 0}; + + if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { + pr_debug("%s: seq%d=0x%x\n", __FUNCTION__, databuf[0], databuf[1]); + mutex_lock(&aw8695->lock); + aw8695->seq[databuf[0]] = (unsigned char)databuf[1]; + aw8695_haptic_set_wav_seq(aw8695, (unsigned char)databuf[0], + aw8695->seq[databuf[0]]); + mutex_unlock(&aw8695->lock); + } + return count; +} + +static ssize_t aw8695_loop_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + size_t count = 0; + unsigned char i = 0; + unsigned char reg_val = 0; + + for(i=0; iloop[i*2+0] = (reg_val>>4)&0x0F; + aw8695->loop[i*2+1] = (reg_val>>0)&0x0F; + + count += snprintf(buf+count, PAGE_SIZE-count, + "seq%d loop: 0x%02x\n", i*2+1, aw8695->loop[i*2+0]); + count += snprintf(buf+count, PAGE_SIZE-count, + "seq%d loop: 0x%02x\n", i*2+2, aw8695->loop[i*2+1]); + } + return count; +} + +static ssize_t aw8695_loop_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[2] = {0, 0}; + + if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { + pr_debug("%s: seq%d loop=0x%x\n", __FUNCTION__, databuf[0], databuf[1]); + mutex_lock(&aw8695->lock); + aw8695->loop[databuf[0]] = (unsigned char)databuf[1]; + aw8695_haptic_set_wav_loop(aw8695, (unsigned char)databuf[0], + aw8695->loop[databuf[0]]); + mutex_unlock(&aw8695->lock); + } + + return count; +} + +static ssize_t aw8695_reg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + unsigned char i = 0; + unsigned char reg_val = 0; + for(i = 0; i < AW8695_REG_MAX; i ++) { + if(!(aw8695_reg_access[i]®_RD_ACCESS)) + continue; + aw8695_i2c_read(aw8695, i, ®_val); + len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%02x=0x%02x \n", i, reg_val); + } + return len; +} + +static ssize_t aw8695_reg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[2] = {0, 0}; + + if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { + aw8695_i2c_write(aw8695, (unsigned char)databuf[0], (unsigned char)databuf[1]); + } + + return count; +} + +static ssize_t aw8695_rtp_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "rtp play: %d\n", aw8695->rtp_cnt); + + return len; +} + +static ssize_t aw8695_rtp_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + aw8695_haptic_stop(aw8695); + aw8695_haptic_set_rtp_aei(aw8695, false); + aw8695_interrupt_clear(aw8695); + if(val < (sizeof(aw8695_rtp_name)/AW8695_RTP_NAME_MAX)) { + aw8695->rtp_file_num = val; + if(val) { + schedule_work(&aw8695->rtp_work); + } + } else { + pr_err("%s: rtp_file_num 0x%02x over max value \n", __func__, aw8695->rtp_file_num); + } + + return count; +} + +static ssize_t aw8695_ram_update_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + //struct timed_output_dev *to_dev = dev_get_drvdata(dev); + //struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + //struct led_classdev *cdev = dev_get_drvdata(dev); + //struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "sram update mode\n"); + return len; +} + +static ssize_t aw8695_ram_update_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + if(val) { + aw8695_ram_update(aw8695); + } + return count; +} + +static ssize_t aw8695_f0_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + + mutex_lock(&aw8695->lock); + aw8695->f0_cali_flag = AW8695_HAPTIC_LRA_F0; + aw8695_haptic_get_f0(aw8695); + mutex_unlock(&aw8695->lock); + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 lra f0 = %d\n", aw8695->f0); + return len; +} + +static ssize_t aw8695_f0_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + //struct timed_output_dev *to_dev = dev_get_drvdata(dev); + //struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + //struct led_classdev *cdev = dev_get_drvdata(dev); + //struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + return count; +} + +static ssize_t aw8695_cali_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + mutex_lock(&aw8695->lock); + aw8695->f0_cali_flag = AW8695_HAPTIC_CALI_F0; + aw8695_haptic_get_f0(aw8695); + mutex_unlock(&aw8695->lock); + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cali f0 = %d\n", aw8695->f0); + return len; +} + +static ssize_t aw8695_cali_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + if(val) { + mutex_lock(&aw8695->lock); + aw8695_haptic_f0_calibration(aw8695); + mutex_unlock(&aw8695->lock); + } + return count; +} + +static ssize_t aw8695_cont_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + aw8695_haptic_read_cont_f0(aw8695); + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cont f0 = %d\n", aw8695->cont_f0); + return len; +} + +static ssize_t aw8695_cont_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + aw8695_haptic_stop(aw8695); + if(val) { + aw8695_haptic_cont(aw8695); + } + return count; +} + + +static ssize_t aw8695_cont_td_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cont delay time = 0x%04x\n", aw8695->cont_td); + return len; +} + +static ssize_t aw8695_cont_td_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[1] = {0}; + if(1 == sscanf(buf, "%x", &databuf[0])) { + aw8695->cont_td = databuf[0]; + aw8695_i2c_write(aw8695, AW8695_REG_TD_H, (unsigned char)(databuf[0]>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_TD_L, (unsigned char)(databuf[0]>>0)); + } + return count; +} + +static ssize_t aw8695_cont_drv_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cont drv level = %d\n", aw8695->cont_drv_lvl); + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cont drv level overdrive= %d\n", aw8695->cont_drv_lvl_ov); + return len; +} + +static ssize_t aw8695_cont_drv_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[2] = {0, 0}; + if(2 == sscanf(buf, "%d %d", &databuf[0], &databuf[1])) { + aw8695->cont_drv_lvl = databuf[0]; + aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL, aw8695->cont_drv_lvl); + aw8695->cont_drv_lvl_ov = databuf[1]; + aw8695_i2c_write(aw8695, AW8695_REG_DRV_LVL_OV, aw8695->cont_drv_lvl_ov); + } + return count; +} + +static ssize_t aw8695_cont_num_brk_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cont break num = %d\n", aw8695->cont_num_brk); + return len; +} + +static ssize_t aw8695_cont_num_brk_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[1] = {0}; + if(1 == sscanf(buf, "%d", &databuf[0])) { + aw8695->cont_num_brk = databuf[0]; + if(aw8695->cont_num_brk > 7) { + aw8695->cont_num_brk = 7; + } + aw8695_i2c_write_bits(aw8695, AW8695_REG_BEMF_NUM, + AW8695_BIT_BEMF_NUM_BRK_MASK, aw8695->cont_num_brk); + } + return count; +} + +static ssize_t aw8695_cont_zc_thr_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695 cont zero cross thr = 0x%04x\n", aw8695->cont_zc_thr); + return len; +} + +static ssize_t aw8695_cont_zc_thr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[1] = {0}; + if(1 == sscanf(buf, "%x", &databuf[0])) { + aw8695->cont_zc_thr = databuf[0]; + aw8695_i2c_write(aw8695, AW8695_REG_ZC_THRSH_H, (unsigned char)(databuf[0]>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_ZC_THRSH_L, (unsigned char)(databuf[0]>>0)); + } + return count; +} + +static ssize_t aw8695_vbat_monitor_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + unsigned char reg_val = 0; + unsigned int vbat = 0; + + mutex_lock(&aw8695->lock); + aw8695_haptic_stop(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_DIAG_GO_MASK, AW8695_BIT_DETCTRL_DIAG_GO_ENABLE); + msleep(2); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_DIAG_GO_MASK, AW8695_BIT_DETCTRL_DIAG_GO_DISABLE); + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_VBAT_GO_MASK, AW8695_BIT_DETCTRL_VABT_GO_ENABLE); + msleep(2); + + aw8695_i2c_read(aw8695, AW8695_REG_VBATDET, ®_val); + vbat = 6100 * reg_val / 256; + + len += snprintf(buf+len, PAGE_SIZE-len, "vbat=%dmV\n", vbat); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_OFF); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + mutex_unlock(&aw8695->lock); + + return len; +} + +static ssize_t aw8695_vbat_monitor_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return count; +} + +static ssize_t aw8695_lra_resistance_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + unsigned char reg_val = 0; + unsigned int r_lra = 0; + + mutex_lock(&aw8695->lock); + aw8695_haptic_stop(aw8695); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BYPASS); + + + aw8695_i2c_write_bits(aw8695, AW8695_REG_ANACTRL, + AW8695_BIT_ANACTRL_HD_PD_MASK, AW8695_BIT_ANACTRL_HD_HZ_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_D2SCFG, + AW8695_BIT_D2SCFG_CLK_ADC_MASK, AW8695_BIT_D2SCFG_CLK_ASC_1P5MHZ); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_RL_OS_MASK, AW8695_BIT_DETCTRL_RL_DETECT); + aw8695_i2c_write_bits(aw8695, AW8695_REG_DETCTRL, + AW8695_BIT_DETCTRL_DIAG_GO_MASK, AW8695_BIT_DETCTRL_DIAG_GO_ENABLE); + msleep(3); + aw8695_i2c_read(aw8695, AW8695_REG_RLDET, ®_val); + r_lra = 298 * reg_val; + len += snprintf(buf+len, PAGE_SIZE-len, "r_lra=%dmohm\n", r_lra); + + + aw8695_i2c_write_bits(aw8695, AW8695_REG_ANACTRL, + AW8695_BIT_ANACTRL_HD_PD_MASK, AW8695_BIT_ANACTRL_HD_PD_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_D2SCFG, + AW8695_BIT_D2SCFG_CLK_ADC_MASK, AW8695_BIT_D2SCFG_CLK_ASC_6MHZ); + + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_OFF); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_BST_MODE_MASK, AW8695_BIT_SYSCTRL_BST_MODE_BOOST); + mutex_unlock(&aw8695->lock); + + return len; +} + +static ssize_t aw8695_lra_resistance_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + return count; +} + +static ssize_t aw8695_auto_boost_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + + len += snprintf(buf+len, PAGE_SIZE-len, "auto_boost=%d\n", aw8695->auto_boost); + + return len; +} + + +static ssize_t aw8695_auto_boost_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int val = 0; + int rc = 0; + + rc = kstrtouint(buf, 0, &val); + if (rc < 0) + return rc; + + mutex_lock(&aw8695->lock); + aw8695_haptic_stop(aw8695); + aw8695_haptic_auto_boost_config(aw8695, val); + mutex_unlock(&aw8695->lock); + + return count; +} + +static ssize_t aw8695_prctmode_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + unsigned char reg_val = 0; + + aw8695_i2c_read(aw8695, AW8695_REG_RLDET, ®_val); + + len += snprintf(buf+len, PAGE_SIZE-len, "prctmode=%d\n", reg_val&0x20); + return len; +} + + +static ssize_t aw8695_prctmode_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + #ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); + #else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); + #endif + unsigned int databuf[2] = {0, 0}; + unsigned int addr=0; + unsigned int val=0; + if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { + addr = databuf[0]; + val=databuf[1]; + mutex_lock(&aw8695->lock); + aw8695_haptic_swicth_motorprotect_config(aw8695, addr, val); + mutex_unlock(&aw8695->lock); + } + return count; +} + +static ssize_t aw8695_haptic_audio_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "%d\n", aw8695->haptic_audio.cnt); + return len; +} + +static ssize_t aw8695_haptic_audio_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[6] = {0}; + + if(6 == sscanf(buf, "%d %d %d %d %d %d", &databuf[0], &databuf[1], &databuf[2], + &databuf[3], &databuf[4], &databuf[5])) { + pr_debug("%s: cnt=%d, cmd=%d, play=%d, wavseq=%d, loop=%d, gain=%d\n", + __func__, databuf[0], databuf[1], databuf[2], databuf[3], + databuf[4], databuf[5]); + mutex_lock(&aw8695->haptic_audio.lock); + aw8695->haptic_audio.data[(unsigned char)databuf[0]].cmd = (unsigned char)databuf[1]; + aw8695->haptic_audio.data[(unsigned char)databuf[0]].play = (unsigned char)databuf[2]; + aw8695->haptic_audio.data[(unsigned char)databuf[0]].wavseq = (unsigned char)databuf[3]; + aw8695->haptic_audio.data[(unsigned char)databuf[0]].loop = (unsigned char)databuf[4]; + aw8695->haptic_audio.data[(unsigned char)databuf[0]].gain = (unsigned char)databuf[5]; + mutex_unlock(&aw8695->haptic_audio.lock); + + if(aw8695->haptic_audio.data[aw8695->haptic_audio.cnt].cmd == 0xff) { + pr_info("%s: haptic_audio stop\n", __func__); + if(hrtimer_active(&aw8695->haptic_audio.timer)) { + pr_info("%s: cancel haptic_audio_timer\n", __func__); + hrtimer_cancel(&aw8695->haptic_audio.timer); + aw8695->haptic_audio.cnt = 0; + aw8695_haptic_set_gain(aw8695, 0x80); + } + } else { + if(hrtimer_active(&aw8695->haptic_audio.timer)) { + } else { + pr_info("%s: start haptic_audio_timer\n", __func__); + hrtimer_start(&aw8695->haptic_audio.timer, + ktime_set(aw8695->haptic_audio.delay_val/1000000, + (aw8695->haptic_audio.delay_val%1000000)*1000), + HRTIMER_MODE_REL); + } + } + } + return count; +} + + +static ssize_t aw8695_haptic_audio_time_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + ssize_t len = 0; + len += snprintf(buf+len, PAGE_SIZE-len, "haptic_audio.delay_val=%dus\n", aw8695->haptic_audio.delay_val); + len += snprintf(buf+len, PAGE_SIZE-len, "haptic_audio.timer_val=%dus\n", aw8695->haptic_audio.timer_val); + return len; +} + +static ssize_t aw8695_haptic_audio_time_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ +#ifdef TIMED_OUTPUT + struct timed_output_dev *to_dev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(to_dev, struct aw8695, to_dev); +#else + struct led_classdev *cdev = dev_get_drvdata(dev); + struct aw8695 *aw8695 = container_of(cdev, struct aw8695, cdev); +#endif + unsigned int databuf[2] = {0}; + + if(2 == sscanf(buf, "%d %d", &databuf[0], &databuf[1])) { + aw8695->haptic_audio.delay_val = databuf[0]; + aw8695->haptic_audio.timer_val = databuf[1]; + } + return count; +} + + +static DEVICE_ATTR(state, S_IWUSR | S_IRUGO, aw8695_state_show, aw8695_state_store); +static DEVICE_ATTR(duration, S_IWUSR | S_IRUGO, aw8695_duration_show, aw8695_duration_store); +static DEVICE_ATTR(activate, S_IWUSR | S_IRUGO, aw8695_activate_show, aw8695_activate_store); +static DEVICE_ATTR(activate_mode, S_IWUSR | S_IRUGO, aw8695_activate_mode_show, aw8695_activate_mode_store); +static DEVICE_ATTR(index, S_IWUSR | S_IRUGO, aw8695_index_show, aw8695_index_store); +static DEVICE_ATTR(vmax, S_IWUSR | S_IRUGO, aw8695_vmax_show, aw8695_vmax_store); +static DEVICE_ATTR(gain, S_IWUSR | S_IRUGO, aw8695_gain_show, aw8695_gain_store); +static DEVICE_ATTR(seq, S_IWUSR | S_IRUGO, aw8695_seq_show, aw8695_seq_store); +static DEVICE_ATTR(loop, S_IWUSR | S_IRUGO, aw8695_loop_show, aw8695_loop_store); +static DEVICE_ATTR(register, S_IWUSR | S_IRUGO, aw8695_reg_show, aw8695_reg_store); +static DEVICE_ATTR(rtp, S_IWUSR | S_IRUGO, aw8695_rtp_show, aw8695_rtp_store); +static DEVICE_ATTR(ram_update, S_IWUSR | S_IRUGO, aw8695_ram_update_show, aw8695_ram_update_store); +static DEVICE_ATTR(f0, S_IWUSR | S_IRUGO, aw8695_f0_show, aw8695_f0_store); +static DEVICE_ATTR(cali, S_IWUSR | S_IRUGO, aw8695_cali_show, aw8695_cali_store); +static DEVICE_ATTR(cont, S_IWUSR | S_IRUGO, aw8695_cont_show, aw8695_cont_store); +static DEVICE_ATTR(cont_td, S_IWUSR | S_IRUGO, aw8695_cont_td_show, aw8695_cont_td_store); +static DEVICE_ATTR(cont_drv, S_IWUSR | S_IRUGO, aw8695_cont_drv_show, aw8695_cont_drv_store); +static DEVICE_ATTR(cont_num_brk, S_IWUSR | S_IRUGO, aw8695_cont_num_brk_show, aw8695_cont_num_brk_store); +static DEVICE_ATTR(cont_zc_thr, S_IWUSR | S_IRUGO, aw8695_cont_zc_thr_show, aw8695_cont_zc_thr_store); +static DEVICE_ATTR(vbat_monitor, S_IWUSR | S_IRUGO, aw8695_vbat_monitor_show, aw8695_vbat_monitor_store); +static DEVICE_ATTR(lra_resistance, S_IWUSR | S_IRUGO, aw8695_lra_resistance_show, aw8695_lra_resistance_store); +static DEVICE_ATTR(auto_boost, S_IWUSR | S_IRUGO, aw8695_auto_boost_show, aw8695_auto_boost_store); +static DEVICE_ATTR(prctmode, S_IWUSR | S_IRUGO, aw8695_prctmode_show, aw8695_prctmode_store); +static DEVICE_ATTR(haptic_audio, S_IWUSR | S_IRUGO, aw8695_haptic_audio_show, aw8695_haptic_audio_store); +static DEVICE_ATTR(haptic_audio_time, S_IWUSR | S_IRUGO, aw8695_haptic_audio_time_show, aw8695_haptic_audio_time_store); + + +static struct attribute *aw8695_vibrator_attributes[] = { + &dev_attr_state.attr, + &dev_attr_duration.attr, + &dev_attr_activate.attr, + &dev_attr_activate_mode.attr, + &dev_attr_index.attr, + &dev_attr_vmax.attr, + &dev_attr_gain.attr, + &dev_attr_seq.attr, + &dev_attr_loop.attr, + &dev_attr_register.attr, + &dev_attr_rtp.attr, + &dev_attr_ram_update.attr, + &dev_attr_f0.attr, + &dev_attr_cali.attr, + &dev_attr_cont.attr, + &dev_attr_cont_td.attr, + &dev_attr_cont_drv.attr, + &dev_attr_cont_num_brk.attr, + &dev_attr_cont_zc_thr.attr, + &dev_attr_vbat_monitor.attr, + &dev_attr_lra_resistance.attr, + &dev_attr_auto_boost.attr, + &dev_attr_prctmode.attr, + &dev_attr_haptic_audio.attr, + &dev_attr_haptic_audio_time.attr, + NULL +}; + +static struct attribute_group aw8695_vibrator_attribute_group = { + .attrs = aw8695_vibrator_attributes +}; + +static enum hrtimer_restart aw8695_vibrator_timer_func(struct hrtimer *timer) +{ + struct aw8695 *aw8695 = container_of(timer, struct aw8695, timer); + + pr_debug("%s enter\n", __func__); + aw8695->state = 0; + schedule_work(&aw8695->vibrator_work); + + return HRTIMER_NORESTART; +} + +static void aw8695_vibrator_work_routine(struct work_struct *work) +{ + struct aw8695 *aw8695 = container_of(work, struct aw8695, vibrator_work); + + pr_debug("%s enter\n", __func__); + + mutex_lock(&aw8695->lock); + + aw8695_haptic_stop(aw8695); + if(aw8695->state) { + if(aw8695->activate_mode == AW8695_HAPTIC_ACTIVATE_RAM_MODE) { + aw8695_haptic_play_repeat_seq(aw8695, true); + } else if(aw8695->activate_mode == AW8695_HAPTIC_ACTIVATE_CONT_MODE) { + aw8695_haptic_cont(aw8695); + } else { + } + } + mutex_unlock(&aw8695->lock); +} + +static int aw8695_vibrator_init(struct aw8695 *aw8695) +{ + int ret = 0; + + pr_info("%s enter\n", __func__); + +#ifdef TIMED_OUTPUT + aw8695->to_dev.name = "vibrator"; + aw8695->to_dev.get_time = aw8695_vibrator_get_time; + aw8695->to_dev.enable = aw8695_vibrator_enable; + + ret = timed_output_dev_register(&(aw8695->to_dev)); + if ( ret < 0){ + dev_err(aw8695->dev, "%s: fail to create timed output dev\n", + __func__); + return ret; + } + ret = sysfs_create_group(&aw8695->to_dev.dev->kobj, &aw8695_vibrator_attribute_group); + if (ret < 0) { + dev_err(aw8695->dev, "%s error creating sysfs attr files\n", __func__); + return ret; + } +#else + aw8695->cdev.name = "vibrator"; + aw8695->cdev.brightness_get = aw8695_haptic_brightness_get; + aw8695->cdev.brightness_set = aw8695_haptic_brightness_set; + + ret = devm_led_classdev_register(&aw8695->i2c->dev, &aw8695->cdev); + if (ret < 0){ + dev_err(aw8695->dev, "%s: fail to create led dev\n", + __func__); + return ret; + } + ret = sysfs_create_group(&aw8695->cdev.dev->kobj, &aw8695_vibrator_attribute_group); + if (ret < 0) { + dev_err(aw8695->dev, "%s error creating sysfs attr files\n", __func__); + return ret; + } +#endif + hrtimer_init(&aw8695->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + aw8695->timer.function = aw8695_vibrator_timer_func; + INIT_WORK(&aw8695->vibrator_work, aw8695_vibrator_work_routine); + + INIT_WORK(&aw8695->rtp_work, aw8695_rtp_work_routine); + + mutex_init(&aw8695->lock); + + return 0; +} + + + + +/****************************************************** + * + * irq + * + ******************************************************/ +static void aw8695_interrupt_clear(struct aw8695 *aw8695) +{ + unsigned char reg_val = 0; + pr_info("%s enter\n", __func__); + aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val); +} + +static void aw8695_interrupt_setup(struct aw8695 *aw8695) +{ + unsigned char reg_val = 0; + + pr_info("%s enter\n", __func__); + + aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val); + + /* edge int mode */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_DBGCTRL, + AW8695_BIT_DBGCTRL_INT_MODE_MASK, AW8695_BIT_DBGCTRL_INT_MODE_EDGE); + + /* int enable */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_BSTERR_MASK, AW8695_BIT_SYSINTM_BSTERR_OFF); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_OV_MASK, AW8695_BIT_SYSINTM_OV_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_UVLO_MASK, AW8695_BIT_SYSINTM_UVLO_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_OCD_MASK, AW8695_BIT_SYSINTM_OCD_EN); + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSINTM, + AW8695_BIT_SYSINTM_OT_MASK, AW8695_BIT_SYSINTM_OT_EN); +} + +static irqreturn_t aw8695_irq(int irq, void *data) +{ + struct aw8695 *aw8695 = data; + unsigned char reg_val = 0; + unsigned char dbg_val = 0; + unsigned int buf_len = 0; + + pr_debug("%s enter\n", __func__); + + aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + pr_info("%s: reg SYSINT=0x%x\n", __func__, reg_val); + aw8695_i2c_read(aw8695, AW8695_REG_DBGSTAT, &dbg_val); + pr_info("%s: reg DBGSTAT=0x%x\n", __func__, dbg_val); + + if(reg_val & AW8695_BIT_SYSINT_OVI) { + pr_err("%s chip ov int error\n", __func__); + } + if(reg_val & AW8695_BIT_SYSINT_UVLI) { + pr_err("%s chip uvlo int error\n", __func__); + } + if(reg_val & AW8695_BIT_SYSINT_OCDI) { + pr_err("%s chip over current int error\n", __func__); + } + if(reg_val & AW8695_BIT_SYSINT_OTI) { + pr_err("%s chip over temperature int error\n", __func__); + } + if(reg_val & AW8695_BIT_SYSINT_DONEI) { + pr_info("%s chip playback done\n", __func__); + } + + if(reg_val & AW8695_BIT_SYSINT_FF_AEI) { + pr_debug("%s: aw8695 rtp fifo almost empty int\n", __func__); + if(aw8695->rtp_init) { + while((!aw8695_haptic_rtp_get_fifo_afi(aw8695)) && + (aw8695->play_mode == AW8695_HAPTIC_RTP_MODE)) { + pr_info("%s: aw8695 rtp mode fifo update, cnt=%d\n", + __func__, aw8695->rtp_cnt); + if((aw8695_rtp->len-aw8695->rtp_cnt) < (aw8695->ram.base_addr>>2)) { + buf_len = aw8695_rtp->len-aw8695->rtp_cnt; + } else { + buf_len = (aw8695->ram.base_addr>>2); + } + aw8695_i2c_writes(aw8695, AW8695_REG_RTP_DATA, + &aw8695_rtp->data[aw8695->rtp_cnt], buf_len); + aw8695->rtp_cnt += buf_len; + if(aw8695->rtp_cnt == aw8695_rtp->len) { + pr_info("%s: rtp update complete\n", __func__); + aw8695_haptic_set_rtp_aei(aw8695, false); + aw8695->rtp_cnt = 0; + aw8695->rtp_init = 0; + break; + } + } + } else { + pr_err("%s: aw8695 rtp init = %d, init error\n", __func__, aw8695->rtp_init); + } + } + + if(reg_val & AW8695_BIT_SYSINT_FF_AFI) { + pr_debug("%s: aw8695 rtp mode fifo full empty\n", __func__); + } + + if(aw8695->play_mode != AW8695_HAPTIC_RTP_MODE) { + aw8695_haptic_set_rtp_aei(aw8695, false); + } + + aw8695_i2c_read(aw8695, AW8695_REG_SYSINT, ®_val); + pr_debug("%s: reg SYSINT=0x%x\n", __func__, reg_val); + aw8695_i2c_read(aw8695, AW8695_REG_SYSST, ®_val); + pr_debug("%s: reg SYSST=0x%x\n", __func__, reg_val); + + pr_debug("%s exit\n", __func__); + + return IRQ_HANDLED; +} + +/***************************************************** + * + * device tree + * + *****************************************************/ +static int aw8695_parse_dt(struct device *dev, struct aw8695 *aw8695, + struct device_node *np) { + aw8695->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); + if (aw8695->reset_gpio < 0) { + dev_err(dev, "%s: no reset gpio provided, will not HW reset device\n", __func__); + return -1; + } else { + dev_info(dev, "%s: reset gpio provided ok\n", __func__); + } + aw8695->irq_gpio = of_get_named_gpio(np, "irq-gpio", 0); + if (aw8695->irq_gpio < 0) { + dev_err(dev, "%s: no irq gpio provided.\n", __func__); + } else { + dev_info(dev, "%s: irq gpio provided ok.\n", __func__); + } + + return 0; +} + +static int aw8695_hw_reset(struct aw8695 *aw8695) +{ + pr_info("%s enter\n", __func__); + + if (aw8695 && gpio_is_valid(aw8695->reset_gpio)) { + gpio_set_value_cansleep(aw8695->reset_gpio, 0); + msleep(1); + gpio_set_value_cansleep(aw8695->reset_gpio, 1); + msleep(1); + } else { + dev_err(aw8695->dev, "%s: failed\n", __func__); + } + return 0; +} + + +/***************************************************** + * + * check chip id + * + *****************************************************/ +static int aw8695_read_chipid(struct aw8695 *aw8695) +{ + int ret = -1; + unsigned char cnt = 0; + unsigned char reg = 0; + + while(cnt < AW_READ_CHIPID_RETRIES) { + /* hardware reset */ + aw8695_hw_reset(aw8695); + + ret = aw8695_i2c_read(aw8695, AW8695_REG_ID, ®); + if (ret < 0) { + dev_err(aw8695->dev, "%s: failed to read register AW8695_REG_ID: %d\n", __func__, ret); + } + switch (reg) { + case AW8695_CHIPID: + pr_info("%s aw8695 detected\n", __func__); + aw8695->chipid = AW8695_CHIPID; + //aw8695->flags |= AW8695_FLAG_SKIP_INTERRUPTS; + aw8695_haptic_softreset(aw8695); + return 0; + default: + pr_info("%s unsupported device revision (0x%x)\n", __func__, reg ); + break; + } + cnt ++; + + msleep(AW_READ_CHIPID_RETRY_DELAY); + } + + return -EINVAL; +} + +/****************************************************** + * + * sys group attribute: reg + * + ******************************************************/ +static ssize_t aw8695_i2c_reg_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw8695 *aw8695 = dev_get_drvdata(dev); + + unsigned int databuf[2] = {0, 0}; + + if(2 == sscanf(buf, "%x %x", &databuf[0], &databuf[1])) { + aw8695_i2c_write(aw8695, (unsigned char)databuf[0], (unsigned char)databuf[1]); + } + + return count; +} + +static ssize_t aw8695_i2c_reg_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct aw8695 *aw8695 = dev_get_drvdata(dev); + ssize_t len = 0; + unsigned char i = 0; + unsigned char reg_val = 0; + for(i = 0; i < AW8695_REG_MAX; i ++) { + if(!(aw8695_reg_access[i]®_RD_ACCESS)) + continue; + aw8695_i2c_read(aw8695, i, ®_val); + len += snprintf(buf+len, PAGE_SIZE-len, "reg:0x%02x=0x%02x \n", i, reg_val); + } + return len; +} +static ssize_t aw8695_i2c_ram_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aw8695 *aw8695 = dev_get_drvdata(dev); + + unsigned int databuf[1] = {0}; + + if(1 == sscanf(buf, "%x", &databuf[0])) { + if(1 == databuf[0]) { + aw8695_ram_update(aw8695); + } + } + + return count; +} + +static ssize_t aw8695_i2c_ram_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct aw8695 *aw8695 = dev_get_drvdata(dev); + ssize_t len = 0; + unsigned int i = 0; + unsigned char reg_val = 0; + + aw8695_haptic_stop(aw8695); + /* RAMINIT Enable */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_EN); + + aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRH, (unsigned char)(aw8695->ram.base_addr>>8)); + aw8695_i2c_write(aw8695, AW8695_REG_RAMADDRL, (unsigned char)(aw8695->ram.base_addr&0x00ff)); + len += snprintf(buf+len, PAGE_SIZE-len, "aw8695_haptic_ram:\n"); + for(i=0; iram.len; i++) { + aw8695_i2c_read(aw8695, AW8695_REG_RAMDATA, ®_val); + len += snprintf(buf+len, PAGE_SIZE-len, "0x%02x,", reg_val); + } + len += snprintf(buf+len, PAGE_SIZE-len, "\n"); + /* RAMINIT Disable */ + aw8695_i2c_write_bits(aw8695, AW8695_REG_SYSCTRL, + AW8695_BIT_SYSCTRL_RAMINIT_MASK, AW8695_BIT_SYSCTRL_RAMINIT_OFF); + + return len; +} + +static DEVICE_ATTR(reg, S_IWUSR | S_IRUGO, aw8695_i2c_reg_show, aw8695_i2c_reg_store); +static DEVICE_ATTR(ram, S_IWUSR | S_IRUGO, aw8695_i2c_ram_show, aw8695_i2c_ram_store); + +static struct attribute *aw8695_attributes[] = { + &dev_attr_reg.attr, + &dev_attr_ram.attr, + NULL +}; + +static struct attribute_group aw8695_attribute_group = { + .attrs = aw8695_attributes +}; + + +/****************************************************** + * + * i2c driver + * + ******************************************************/ +static int aw8695_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + struct aw8695 *aw8695; + struct device_node *np = i2c->dev.of_node; + int irq_flags = 0; + int ret = -1; + + pr_info("%s enter\n", __func__); + + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) { + dev_err(&i2c->dev, "check_functionality failed\n"); + return -EIO; + } + + aw8695 = devm_kzalloc(&i2c->dev, sizeof(struct aw8695), GFP_KERNEL); + if (aw8695 == NULL) + return -ENOMEM; + + aw8695->dev = &i2c->dev; + aw8695->i2c = i2c; + + i2c_set_clientdata(i2c, aw8695); + + /* aw8695 rst & int */ + if (np) { + ret = aw8695_parse_dt(&i2c->dev, aw8695, np); + if (ret) { + dev_err(&i2c->dev, "%s: failed to parse device tree node\n", __func__); + goto err_parse_dt; + } + } else { + aw8695->reset_gpio = -1; + aw8695->irq_gpio = -1; + } + + if (gpio_is_valid(aw8695->reset_gpio)) { + ret = devm_gpio_request_one(&i2c->dev, aw8695->reset_gpio, + GPIOF_OUT_INIT_LOW, "aw8695_rst"); + if (ret){ + dev_err(&i2c->dev, "%s: rst request failed\n", __func__); + goto err_gpio_request; + } + } + + if (gpio_is_valid(aw8695->irq_gpio)) { + ret = devm_gpio_request_one(&i2c->dev, aw8695->irq_gpio, + GPIOF_DIR_IN, "aw8695_int"); + if (ret){ + dev_err(&i2c->dev, "%s: int request failed\n", __func__); + goto err_gpio_request; + } + } + + /* aw8695 chip id */ + ret = aw8695_read_chipid(aw8695); + if (ret < 0) { + dev_err(&i2c->dev, "%s: aw8695_read_chipid failed ret=%d\n", __func__, ret); + goto err_id; + } + + /* aw8695 irq */ + if (gpio_is_valid(aw8695->irq_gpio) && + !(aw8695->flags & AW8695_FLAG_SKIP_INTERRUPTS)) { + /* register irq handler */ + aw8695_interrupt_setup(aw8695); + irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + ret = devm_request_threaded_irq(&i2c->dev, + gpio_to_irq(aw8695->irq_gpio), + NULL, aw8695_irq, irq_flags, + "aw8695", aw8695); + if (ret != 0) { + dev_err(&i2c->dev, "%s: failed to request IRQ %d: %d\n", + __func__, gpio_to_irq(aw8695->irq_gpio), ret); + goto err_irq; + } + } else { + dev_info(&i2c->dev, "%s skipping IRQ registration\n", __func__); + /* disable feature support if gpio was invalid */ + aw8695->flags |= AW8695_FLAG_SKIP_INTERRUPTS; + } + + dev_set_drvdata(&i2c->dev, aw8695); + + ret = sysfs_create_group(&i2c->dev.kobj, &aw8695_attribute_group); + if (ret < 0) { + dev_info(&i2c->dev, "%s error creating sysfs attr files\n", __func__); + goto err_sysfs; + } + + g_aw8695 = aw8695; + + aw8695_vibrator_init(aw8695); + + aw8695_haptic_init(aw8695); + + aw8695_ram_init(aw8695); + + pr_info("%s probe completed successfully!\n", __func__); + + return 0; + +err_sysfs: + devm_free_irq(&i2c->dev, gpio_to_irq(aw8695->irq_gpio), aw8695); +err_irq: +err_id: + if (gpio_is_valid(aw8695->irq_gpio)) + devm_gpio_free(&i2c->dev, aw8695->irq_gpio); + if (gpio_is_valid(aw8695->reset_gpio)) + devm_gpio_free(&i2c->dev, aw8695->reset_gpio); +err_gpio_request: +err_parse_dt: + devm_kfree(&i2c->dev, aw8695); + aw8695 = NULL; + return ret; +} + +static int aw8695_i2c_remove(struct i2c_client *i2c) +{ + struct aw8695 *aw8695 = i2c_get_clientdata(i2c); + + pr_info("%s enter\n", __func__); + + sysfs_remove_group(&i2c->dev.kobj, &aw8695_attribute_group); + + devm_free_irq(&i2c->dev, gpio_to_irq(aw8695->irq_gpio), aw8695); + + if (gpio_is_valid(aw8695->irq_gpio)) + devm_gpio_free(&i2c->dev, aw8695->irq_gpio); + if (gpio_is_valid(aw8695->reset_gpio)) + devm_gpio_free(&i2c->dev, aw8695->reset_gpio); + + devm_kfree(&i2c->dev, aw8695); + aw8695 = NULL; + + return 0; +} + +static const struct i2c_device_id aw8695_i2c_id[] = { + { AW8695_I2C_NAME, 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aw8695_i2c_id); + +static struct of_device_id aw8695_dt_match[] = { + { .compatible = "awinic,aw8695_haptic" }, + { }, +}; + +static struct i2c_driver aw8695_i2c_driver = { + .driver = { + .name = AW8695_I2C_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(aw8695_dt_match), + }, + .probe = aw8695_i2c_probe, + .remove = aw8695_i2c_remove, + .id_table = aw8695_i2c_id, +}; + + +static int __init aw8695_i2c_init(void) +{ + int ret = 0; + + pr_info("aw8695 driver version %s\n", AW8695_VERSION); + + ret = i2c_add_driver(&aw8695_i2c_driver); + if(ret){ + pr_err("fail to add aw8695 device into i2c\n"); + return ret; + } + + return 0; +} +//late_initcall(aw8695_i2c_init); +module_init(aw8695_i2c_init); + + +static void __exit aw8695_i2c_exit(void) +{ + i2c_del_driver(&aw8695_i2c_driver); +} +module_exit(aw8695_i2c_exit); + + +MODULE_DESCRIPTION("AW8695 Haptic Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/misc/aw8695_haptic/aw8695.h b/drivers/misc/aw8695_haptic/aw8695.h index dd0757ad88f1..b44143c57a5c 100644 --- a/drivers/misc/aw8695_haptic/aw8695.h +++ b/drivers/misc/aw8695_haptic/aw8695.h @@ -32,7 +32,7 @@ * marco * ********************************************************/ -#define MAX_I2C_BUFFER_SIZE 65536 +#define MAX_I2C_BUFFER_SIZE 65536 #define AW8695_REG_MAX 0xff @@ -43,25 +43,92 @@ #define HAPTIC_MAX_TIMEOUT 10000 -#define AW8695_HAPTIC_F0_PRE 2350 -#define AW8695_HAPTIC_F0_DRV_LVL 95 -#define AW8695_HAPTIC_F0_COEFF 260 //2.604167 -#define AW8695_OPEN_PLAYBACK 0 +/* motor config */ +//#define LRA_0619 +#define LRA_0832 + +#ifdef LRA_0619 +#define AW8695_HAPTIC_F0_PRE 1700 // 170Hz +#define AW8695_HAPTIC_F0_CALI_PERCEN 7 // -7%~7% +#define AW8695_HAPTIC_CONT_DRV_LVL 105 // 105*6.1/256=2.50v +#define AW8695_HAPTIC_CONT_DRV_LVL_OV 125 // 125*6.1/256=2.98v +#define AW8695_HAPTIC_CONT_TD 0x009a +#define AW8695_HAPTIC_CONT_ZC_THR 0x0ff1 +#define AW8695_HAPTIC_CONT_NUM_BRK 3 +#endif + +#ifdef LRA_0832 +#define AW8695_HAPTIC_F0_PRE 2350 // 235Hz +#define AW8695_HAPTIC_F0_CALI_PERCEN 7 // -7%~7% +#define AW8695_HAPTIC_CONT_DRV_LVL 95 +#define AW8695_HAPTIC_CONT_DRV_LVL_OV 0x70 // 155*6.1/256=3.69v +#define AW8695_HAPTIC_CONT_TD 0x0073 +#define AW8695_HAPTIC_CONT_ZC_THR 0x0ff1 +#define AW8695_HAPTIC_CONT_NUM_BRK 3 +#endif + + +#define AW8695_HAPTIC_F0_COEFF 260 //2.604167 + + +/* trig config */ +#define AW8695_TRG1_ENABLE 1 +#define AW8695_TRG2_ENABLE 1 +#define AW8695_TRG3_ENABLE 1 + +#define AW8695_TRG1_DEFAULT_LEVEL 1 // 1: high level; 0: low level +#define AW8695_TRG2_DEFAULT_LEVEL 1 // 1: high level; 0: low level +#define AW8695_TRG3_DEFAULT_LEVEL 1 // 1: high level; 0: low level + +#if AW8695_TRG1_ENABLE +#define AW8695_TRG1_DEFAULT_ENABLE AW8695_BIT_TRGCFG2_TRG1_ENABLE +#else +#define AW8695_TRG1_DEFAULT_ENABLE AW8695_BIT_TRGCFG2_TRG1_DISABLE +#endif + +#if AW8695_TRG2_ENABLE +#define AW8695_TRG2_DEFAULT_ENABLE AW8695_BIT_TRGCFG2_TRG2_ENABLE +#else +#define AW8695_TRG2_DEFAULT_ENABLE AW8695_BIT_TRGCFG2_TRG2_DISABLE +#endif + +#if AW8695_TRG3_ENABLE +#define AW8695_TRG3_DEFAULT_ENABLE AW8695_BIT_TRGCFG2_TRG3_ENABLE +#else +#define AW8695_TRG3_DEFAULT_ENABLE AW8695_BIT_TRGCFG2_TRG3_DISABLE +#endif + +#if AW8695_TRG1_DEFAULT_LEVEL +#define AW8695_TRG1_DEFAULT_POLAR AW8695_BIT_TRGCFG1_TRG1_POLAR_POS +#else +#define AW8695_TRG1_DEFAULT_POLAR AW8695_BIT_TRGCFG1_TRG1_POLAR_NEG +#endif + +#if AW8695_TRG2_DEFAULT_LEVEL +#define AW8695_TRG2_DEFAULT_POLAR AW8695_BIT_TRGCFG1_TRG2_POLAR_POS +#else +#define AW8695_TRG2_DEFAULT_POLAR AW8695_BIT_TRGCFG1_TRG2_POLAR_NEG +#endif + +#if AW8695_TRG3_DEFAULT_LEVEL +#define AW8695_TRG3_DEFAULT_POLAR AW8695_BIT_TRGCFG1_TRG3_POLAR_POS +#else +#define AW8695_TRG3_DEFAULT_POLAR AW8695_BIT_TRGCFG1_TRG3_POLAR_NEG +#endif + +enum ram_mode_seq { + AW8695_LONG_RAM = 1, + AW8695_SHORT_RAM_20_UP = 2, + AW8695_SHORT_RAM_60_UP = 3, + AW8695_SHORT_RAM_80_UP = 4, + AW8695_SHORT_RAM_100_UP = 5, +}; enum aw8695_flags { AW8695_FLAG_NONR = 0, AW8695_FLAG_SKIP_INTERRUPTS = 1, }; -enum aw8695_chipids { - AW8690_ID = 0, - AW8691_ID = 1, - AW8694_ID = 4, - AW8695_ID = 5, - AW8696_ID = 6, - AW8697_ID = 7, -}; - enum aw8695_haptic_read_write { AW8695_HAPTIC_CMD_READ_REG = 0, AW8695_HAPTIC_CMD_WRITE_REG = 1, @@ -74,6 +141,7 @@ enum aw8695_haptic_work_mode { AW8695_HAPTIC_RTP_MODE = 2, AW8695_HAPTIC_TRIG_MODE = 3, AW8695_HAPTIC_CONT_MODE = 4, + AW8695_HAPTIC_RAM_LOOP_MODE = 5, }; enum aw8695_haptic_bst_mode { @@ -81,6 +149,22 @@ enum aw8695_haptic_bst_mode { AW8695_HAPTIC_BOOST_MODE = 1, }; +enum aw8695_haptic_activate_mode { + AW8695_HAPTIC_ACTIVATE_RAM_MODE = 0, + AW8695_HAPTIC_ACTIVATE_CONT_MODE = 1, +}; + + +enum aw8695_haptic_vbat_comp_mode { + AW8695_HAPTIC_VBAT_SW_COMP_MODE = 0, + AW8695_HAPTIC_VBAT_HW_COMP_MODE = 1, +}; + +enum aw8695_haptic_f0_flag { + AW8695_HAPTIC_LRA_F0 = 0, + AW8695_HAPTIC_CALI_F0 = 1, +}; + enum aw8695_haptic_pwm_mode { AW8695_PWM_48K = 0, AW8695_PWM_24K = 1, @@ -155,6 +239,10 @@ struct aw8695 { unsigned char play_mode; + unsigned char activate_mode; + + unsigned char auto_boost; + int state; int duration; int amplitude; @@ -173,9 +261,15 @@ struct aw8695 { unsigned int f0; unsigned int f0_pre; - unsigned char f0_drv_lvl; + unsigned int cont_f0; + unsigned int cont_td; + unsigned int cont_zc_thr; + unsigned char cont_drv_lvl; + unsigned char cont_drv_lvl_ov; + unsigned char cont_num_brk; unsigned char max_pos_beme; unsigned char max_neg_beme; + unsigned char f0_cali_flag; struct haptic_audio haptic_audio; }; diff --git a/drivers/misc/aw8695_haptic/aw8695_config.h b/drivers/misc/aw8695_haptic/aw8695_config.h new file mode 100644 index 000000000000..ba0444d30327 --- /dev/null +++ b/drivers/misc/aw8695_haptic/aw8695_config.h @@ -0,0 +1,12 @@ +#ifndef __AW8695_CONFIG_H__ +#define __AW8695_CONFIG_H__ + +#define AW8695_CHIPID 0x95 + +#define AW8695_BSTCFG_PEAKCUR_LIMIT 0x03 +#define AW8695_DEFAULT_PEAKCUR AW8695_BIT_BSTCFG_PEAKCUR_2A + +#define AW8695_CONT_PLAYBACK_MODE AW8695_BIT_CONT_CTRL_CLOSE_PLAYBACK + + +#endif diff --git a/drivers/misc/aw8695_haptic/aw8695_reg.h b/drivers/misc/aw8695_haptic/aw8695_reg.h index af8be9c0f9a8..e77ab7f4a195 100644 --- a/drivers/misc/aw8695_haptic/aw8695_reg.h +++ b/drivers/misc/aw8695_haptic/aw8695_reg.h @@ -46,7 +46,7 @@ #define AW8695_REG_END_DLY_L 0x2a #define AW8695_REG_DATCTRL 0x2b #define AW8695_REG_PWMDEL 0x2c -#define AW8695_REG_PWMPRE 0x2d +#define AW8695_REG_PWMPRC 0x2d #define AW8695_REG_PWMDBG 0x2e #define AW8695_REG_LDOCTRL 0x2f #define AW8695_REG_DBGSTAT 0x30 @@ -69,7 +69,7 @@ #define AW8695_REG_RAMADDRL 0x41 #define AW8695_REG_RAMDATA 0x42 #define AW8695_REG_GLB_STATE 0x46 -#define AW8695_REG_BAT_AUTO 0x47 +#define AW8695_REG_BST_AUTO 0x47 #define AW8695_REG_CONT_CTRL 0x48 #define AW8695_REG_F_PRE_H 0x49 #define AW8695_REG_F_PRE_L 0x4a @@ -164,7 +164,7 @@ const unsigned char aw8695_reg_access[AW8695_REG_MAX]={ [AW8695_REG_END_DLY_L ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_DATCTRL ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_PWMDEL ] = REG_RD_ACCESS|REG_WR_ACCESS, - [AW8695_REG_PWMPRE ] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW8695_REG_PWMPRC ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_PWMDBG ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_LDOCTRL ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_DBGSTAT ] = REG_RD_ACCESS, @@ -187,7 +187,7 @@ const unsigned char aw8695_reg_access[AW8695_REG_MAX]={ [AW8695_REG_RAMADDRL ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_RAMDATA ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_GLB_STATE ] = REG_RD_ACCESS|REG_WR_ACCESS, - [AW8695_REG_BAT_AUTO ] = REG_RD_ACCESS|REG_WR_ACCESS, + [AW8695_REG_BST_AUTO ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_CONT_CTRL ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_F_PRE_H ] = REG_RD_ACCESS|REG_WR_ACCESS, [AW8695_REG_F_PRE_L ] = REG_RD_ACCESS|REG_WR_ACCESS, @@ -234,248 +234,311 @@ const unsigned char aw8695_reg_access[AW8695_REG_MAX]={ /****************************************************** * Register Detail *****************************************************/ -// SYSST -#define AW8695_BIT_SYSST_BSTERRS (1<<7) -#define AW8695_BIT_SYSST_OVS (1<<6) -#define AW8695_BIT_SYSST_UVLS (1<<5) -#define AW8695_BIT_SYSST_FF_AES (1<<4) -#define AW8695_BIT_SYSST_FF_AFS (1<<3) -#define AW8695_BIT_SYSST_OCDS (1<<2) -#define AW8695_BIT_SYSST_OTS (1<<1) -#define AW8695_BIT_SYSST_DONES (1<<0) - -// SYSINT -#define AW8695_BIT_SYSINT_BSTERRI (1<<7) -#define AW8695_BIT_SYSINT_OVI (1<<6) -#define AW8695_BIT_SYSINT_UVLI (1<<5) -#define AW8695_BIT_SYSINT_FF_AEI (1<<4) -#define AW8695_BIT_SYSINT_FF_AFI (1<<3) -#define AW8695_BIT_SYSINT_OCDI (1<<2) -#define AW8695_BIT_SYSINT_OTI (1<<1) -#define AW8695_BIT_SYSINT_DONEI (1<<0) - -// SYSINTM -#define AW8695_BIT_SYSINTM_BSTERR_MASK (~(1<<7)) -#define AW8695_BIT_SYSINTM_BSTERR_OFF (1<<7) -#define AW8695_BIT_SYSINTM_BSTERR_EN (0<<7) -#define AW8695_BIT_SYSINTM_OV_MASK (~(1<<6)) -#define AW8695_BIT_SYSINTM_OV_OFF (1<<6) -#define AW8695_BIT_SYSINTM_OV_EN (0<<6) -#define AW8695_BIT_SYSINTM_UVLO_MASK (~(1<<5)) -#define AW8695_BIT_SYSINTM_UVLO_OFF (1<<5) -#define AW8695_BIT_SYSINTM_UVLO_EN (0<<5) -#define AW8695_BIT_SYSINTM_FF_AE_MASK (~(1<<4)) -#define AW8695_BIT_SYSINTM_FF_AE_OFF (1<<4) -#define AW8695_BIT_SYSINTM_FF_AE_EN (0<<4) -#define AW8695_BIT_SYSINTM_FF_AF_MASK (~(1<<3)) -#define AW8695_BIT_SYSINTM_FF_AF_OFF (1<<3) -#define AW8695_BIT_SYSINTM_FF_AF_EN (0<<3) -#define AW8695_BIT_SYSINTM_OCD_MASK (~(1<<2)) -#define AW8695_BIT_SYSINTM_OCD_OFF (1<<2) -#define AW8695_BIT_SYSINTM_OCD_EN (0<<2) -#define AW8695_BIT_SYSINTM_OT_MASK (~(1<<1)) -#define AW8695_BIT_SYSINTM_OT_OFF (1<<1) -#define AW8695_BIT_SYSINTM_OT_EN (0<<1) -#define AW8695_BIT_SYSINTM_DONE_MASK (~(1<<0)) -#define AW8695_BIT_SYSINTM_DONE_OFF (1<<0) -#define AW8695_BIT_SYSINTM_DONE_EN (0<<0) - -// SYSCTRL -#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6)) -#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6) -#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6) -#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6) -#define AW8695_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5)) -#define AW8695_BIT_SYSCTRL_RAMINIT_EN (1<<5) -#define AW8695_BIT_SYSCTRL_RAMINIT_OFF (0<<5) -#define AW8695_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2)) -#define AW8695_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2) -#define AW8695_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2) -#define AW8695_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2) -#define AW8695_BIT_SYSCTRL_BST_MODE_MASK (~(1<<1)) -#define AW8695_BIT_SYSCTRL_BST_MODE_BOOST (1<<1) -#define AW8695_BIT_SYSCTRL_BST_MODE_BYPASS (0<<1) -#define AW8695_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0)) -#define AW8695_BIT_SYSCTRL_STANDBY (1<<0) -#define AW8695_BIT_SYSCTRL_ACTIVE (0<<0) - -// GO -#define AW8695_BIT_GO_MASK (~(1<<0)) -#define AW8695_BIT_GO_ENABLE (1<<0) -#define AW8695_BIT_GO_DISABLE (0<<0) - -// WAVSEQ1 -#define AW8695_BIT_WAVSEQ1_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0)) - -// WAVSEQ2 -#define AW8695_BIT_WAVSEQ2_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0)) - -// WAVSEQ3 -#define AW8695_BIT_WAVSEQ3_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0)) - -// WAVSEQ4 -#define AW8695_BIT_WAVSEQ4_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0)) - -// WAVSEQ5 -#define AW8695_BIT_WAVSEQ5_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0)) - -// WAVSEQ6 -#define AW8695_BIT_WAVSEQ6_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0)) - -// WAVSEQ7 -#define AW8695_BIT_WAVSEQ7_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0)) - -// WAVSEQ8 -#define AW8695_BIT_WAVSEQ8_WAIT (1<<7) -#define AW8695_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0)) - -// WAVLOOP -#define AW8695_BIT_WAVLOOP_SEQN_MASK (~(15<<4)) -#define AW8695_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0)) -#define AW8695_BIT_WAVLOOP_INIFINITELY (15<<0) - -// WAVLOOP1 -#define AW8695_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4)) -#define AW8695_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0)) - -// WAVLOOP2 -#define AW8695_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4)) -#define AW8695_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0)) - -// WAVLOOP3 -#define AW8695_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4)) -#define AW8695_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0)) - -// WAVLOOP4 -#define AW8695_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4)) -#define AW8695_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0)) - - -// PLAYPRIO -#define AW8695_BIT_PLAYPRIO_GO_MASK (~(3<<6)) -#define AW8695_BIT_PLAYPRIO_TRIG3_MASK (~(3<<4)) -#define AW8695_BIT_PLAYPRIO_TRIG2_MASK (~(3<<2)) -#define AW8695_BIT_PLAYPRIO_TRIG1_MASK (~(3<<0)) - -// TRGCFG1 -#define AW8695_BIT_TRGCFG1_TRG3_POLAR_MASK (~(1<<5)) -#define AW8695_BIT_TRGCFG1_TRG3_POLAR_NEG (1<<5) -#define AW8695_BIT_TRGCFG1_TRG3_POLAR_POS (0<<5) -#define AW8695_BIT_TRGCFG1_TRG3_EDGE_MASK (~(1<<4)) -#define AW8695_BIT_TRGCFG1_TRG3_EDGE_POS (1<<4) -#define AW8695_BIT_TRGCFG1_TRG3_EDGE_POS_NEG (0<<4) -#define AW8695_BIT_TRGCFG1_TRG2_POLAR_MASK (~(1<<3)) -#define AW8695_BIT_TRGCFG1_TRG2_POLAR_NEG (1<<3) -#define AW8695_BIT_TRGCFG1_TRG2_POLAR_POS (0<<3) -#define AW8695_BIT_TRGCFG1_TRG2_EDGE_MASK (~(1<<2)) -#define AW8695_BIT_TRGCFG1_TRG2_EDGE_POS (1<<2) -#define AW8695_BIT_TRGCFG1_TRG2_EDGE_POS_NEG (0<<2) -#define AW8695_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1)) -#define AW8695_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1) -#define AW8695_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1) -#define AW8695_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0)) -#define AW8695_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0) -#define AW8695_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0) - -// TRGCFG2 -#define AW8695_BIT_TRGCFG2_TRG3_ENABLE_MASK (~(1<<2)) -#define AW8695_BIT_TRGCFG2_TRG3_ENABLE (1<<2) -#define AW8695_BIT_TRGCFG2_TRG3_DISABLE (0<<2) -#define AW8695_BIT_TRGCFG2_TRG2_ENABLE_MASK (~(1<<1)) -#define AW8695_BIT_TRGCFG2_TRG2_ENABLE (1<<1) -#define AW8695_BIT_TRGCFG2_TRG2_DISABLE (0<<1) -#define AW8695_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0)) -#define AW8695_BIT_TRGCFG2_TRG1_ENABLE (1<<0) -#define AW8695_BIT_TRGCFG2_TRG1_DISABLE (0<<0) - -// DATCTRL -#define AW8695_BIT_DATCTRL_FC_MASK (~(1<<6)) -#define AW8695_BIT_DATCTRL_FC_1000HZ (3<<6) -#define AW8695_BIT_DATCTRL_FC_800HZ (3<<6) -#define AW8695_BIT_DATCTRL_FC_600HZ (1<<6) -#define AW8695_BIT_DATCTRL_FC_400HZ (0<<6) -#define AW8695_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5)) -#define AW8695_BIT_DATCTRL_LPF_ENABLE (1<<5) -#define AW8695_BIT_DATCTRL_LPF_DISABLE (0<<5) - - -// PWMDBG -#define AW8695_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5)) -#define AW8695_BIT_PWMDBG_PWM_12K (3<<5) -#define AW8695_BIT_PWMDBG_PWM_24K (2<<5) -#define AW8695_BIT_PWMDBG_PWM_48K (0<<5) - - -// CONT_CTRL -#define AW8695_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7)) -#define AW8695_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7) -#define AW8695_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7) -#define AW8695_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5)) -#define AW8695_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5) -#define AW8695_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5) -#define AW8695_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5) -#define AW8695_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5) -#define AW8695_BIT_CONT_CTRL_MODE_MASK (~(1<<4)) -#define AW8695_BIT_CONT_CTRL_BY_DRV_TIME (1<<4) -#define AW8695_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4) -#define AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3)) -#define AW8695_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3) -#define AW8695_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3) -#define AW8695_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2)) -#define AW8695_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2) -#define AW8695_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2) -#define AW8695_BIT_CONT_CTRL_O2C_MASK (~(1<<1)) -#define AW8695_BIT_CONT_CTRL_O2C_ENABLE (1<<1) -#define AW8695_BIT_CONT_CTRL_O2C_DISABLE (0<<1) -#define AW8695_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0)) -#define AW8695_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0) -#define AW8695_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0) - - -// DETCTRL -#define AW8695_BIT_DETCTRL_RL_OS_MASK (~(1<<6)) -#define AW8695_BIT_DETCTRL_RL_DETECT (1<<6) -#define AW8695_BIT_DETCTRL_OS_DETECT (0<<6) -#define AW8695_BIT_DETCTRL_PROTECT_MASK (~(1<<5)) -#define AW8695_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5) -#define AW8695_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5) -#define AW8695_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1)) -#define AW8695_BIT_DETCTRL_VABT_GO_ENABLE (1<<1) -#define AW8695_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1) -#define AW8695_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0)) -#define AW8695_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0) -#define AW8695_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0) - - -// VBAT MODE -#define AW8695_BIT_DETCTRL_VBAT_MODE_MASK (~(1<<6)) -#define AW8695_BIT_DETCTRL_VBAT_HW_COMP (1<<6) -#define AW8695_BIT_DETCTRL_VBAT_SW_COMP (0<<6) - -// BSTCFG -#define AW8695_BIT_BSTCFG_PEAKCUR_MASK (~(7<<0)) -#define AW8695_BIT_BSTCFG_PEAKCUR_4A (7<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_3P75A (6<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_3P5A (5<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_3P25A (4<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_3A (3<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_2P5A (2<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_2A (1<<0) -#define AW8695_BIT_BSTCFG_PEAKCUR_1P5A (0<<0) - -// BSTDBG4 -#define AW8695_BIT_BSTCFG_BSTVOL_MASK (~(31<<3)) - -// ANACTRL -#define AW8695_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5)) -#define AW8695_BIT_ANACTRL_LRA_SRC_REG (1<<5) -#define AW8695_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5) +// SYSST: reg0x01 +#define AW8695_BIT_SYSST_BSTERRS (1<<7) +#define AW8695_BIT_SYSST_OVS (1<<6) +#define AW8695_BIT_SYSST_UVLS (1<<5) +#define AW8695_BIT_SYSST_FF_AES (1<<4) +#define AW8695_BIT_SYSST_FF_AFS (1<<3) +#define AW8695_BIT_SYSST_OCDS (1<<2) +#define AW8695_BIT_SYSST_OTS (1<<1) +#define AW8695_BIT_SYSST_DONES (1<<0) + +// SYSINT: reg0x02 +#define AW8695_BIT_SYSINT_BSTERRI (1<<7) +#define AW8695_BIT_SYSINT_OVI (1<<6) +#define AW8695_BIT_SYSINT_UVLI (1<<5) +#define AW8695_BIT_SYSINT_FF_AEI (1<<4) +#define AW8695_BIT_SYSINT_FF_AFI (1<<3) +#define AW8695_BIT_SYSINT_OCDI (1<<2) +#define AW8695_BIT_SYSINT_OTI (1<<1) +#define AW8695_BIT_SYSINT_DONEI (1<<0) + +// SYSINTM: reg0x03 +#define AW8695_BIT_SYSINTM_BSTERR_MASK (~(1<<7)) +#define AW8695_BIT_SYSINTM_BSTERR_OFF (1<<7) +#define AW8695_BIT_SYSINTM_BSTERR_EN (0<<7) +#define AW8695_BIT_SYSINTM_OV_MASK (~(1<<6)) +#define AW8695_BIT_SYSINTM_OV_OFF (1<<6) +#define AW8695_BIT_SYSINTM_OV_EN (0<<6) +#define AW8695_BIT_SYSINTM_UVLO_MASK (~(1<<5)) +#define AW8695_BIT_SYSINTM_UVLO_OFF (1<<5) +#define AW8695_BIT_SYSINTM_UVLO_EN (0<<5) +#define AW8695_BIT_SYSINTM_FF_AE_MASK (~(1<<4)) +#define AW8695_BIT_SYSINTM_FF_AE_OFF (1<<4) +#define AW8695_BIT_SYSINTM_FF_AE_EN (0<<4) +#define AW8695_BIT_SYSINTM_FF_AF_MASK (~(1<<3)) +#define AW8695_BIT_SYSINTM_FF_AF_OFF (1<<3) +#define AW8695_BIT_SYSINTM_FF_AF_EN (0<<3) +#define AW8695_BIT_SYSINTM_OCD_MASK (~(1<<2)) +#define AW8695_BIT_SYSINTM_OCD_OFF (1<<2) +#define AW8695_BIT_SYSINTM_OCD_EN (0<<2) +#define AW8695_BIT_SYSINTM_OT_MASK (~(1<<1)) +#define AW8695_BIT_SYSINTM_OT_OFF (1<<1) +#define AW8695_BIT_SYSINTM_OT_EN (0<<1) +#define AW8695_BIT_SYSINTM_DONE_MASK (~(1<<0)) +#define AW8695_BIT_SYSINTM_DONE_OFF (1<<0) +#define AW8695_BIT_SYSINTM_DONE_EN (0<<0) + +// SYSCTRL: reg0x04 +#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_MASK (~(3<<6)) +#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_4X (3<<6) +#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_2X (0<<6) +#define AW8695_BIT_SYSCTRL_WAVDAT_MODE_1X (1<<6) +#define AW8695_BIT_SYSCTRL_RAMINIT_MASK (~(1<<5)) +#define AW8695_BIT_SYSCTRL_RAMINIT_EN (1<<5) +#define AW8695_BIT_SYSCTRL_RAMINIT_OFF (0<<5) +#define AW8695_BIT_SYSCTRL_PLAY_MODE_MASK (~(3<<2)) +#define AW8695_BIT_SYSCTRL_PLAY_MODE_CONT (2<<2) +#define AW8695_BIT_SYSCTRL_PLAY_MODE_RTP (1<<2) +#define AW8695_BIT_SYSCTRL_PLAY_MODE_RAM (0<<2) +#define AW8695_BIT_SYSCTRL_BST_MODE_MASK (~(1<<1)) +#define AW8695_BIT_SYSCTRL_BST_MODE_BOOST (1<<1) +#define AW8695_BIT_SYSCTRL_BST_MODE_BYPASS (0<<1) +#define AW8695_BIT_SYSCTRL_WORK_MODE_MASK (~(1<<0)) +#define AW8695_BIT_SYSCTRL_STANDBY (1<<0) +#define AW8695_BIT_SYSCTRL_ACTIVE (0<<0) + +// GO: reg0x05 +#define AW8695_BIT_GO_MASK (~(1<<0)) +#define AW8695_BIT_GO_ENABLE (1<<0) +#define AW8695_BIT_GO_DISABLE (0<<0) + +// WAVSEQ1: reg0x07 +#define AW8695_BIT_WAVSEQ1_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ1_WAV_FRM_SEQ1_MASK (~(127<<0)) + +// WAVSEQ2: reg0x08 +#define AW8695_BIT_WAVSEQ2_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ2_WAV_FRM_SEQ2_MASK (~(127<<0)) + +// WAVSEQ3: reg0x09 +#define AW8695_BIT_WAVSEQ3_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ3_WAV_FRM_SEQ3_MASK (~(127<<0)) + +// WAVSEQ4: reg0x0a +#define AW8695_BIT_WAVSEQ4_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ4_WAV_FRM_SEQ4_MASK (~(127<<0)) + +// WAVSEQ5: reg0x0b +#define AW8695_BIT_WAVSEQ5_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ5_WAV_FRM_SEQ5_MASK (~(127<<0)) + +// WAVSEQ6: reg0x0c +#define AW8695_BIT_WAVSEQ6_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ6_WAV_FRM_SEQ6_MASK (~(127<<0)) + +// WAVSEQ7: reg0x0d +#define AW8695_BIT_WAVSEQ7_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ7_WAV_FRM_SEQ7_MASK (~(127<<0)) + +// WAVSEQ8: reg0x0e +#define AW8695_BIT_WAVSEQ8_WAIT (1<<7) +#define AW8695_BIT_WAVSEQ8_WAV_FRM_SEQ8_MASK (~(127<<0)) + +// WAVLOOP: +#define AW8695_BIT_WAVLOOP_SEQN_MASK (~(15<<4)) +#define AW8695_BIT_WAVLOOP_SEQNP1_MASK (~(15<<0)) +#define AW8695_BIT_WAVLOOP_INIFINITELY (15<<0) + +// WAVLOOP1: reg0x0f +#define AW8695_BIT_WAVLOOP1_SEQ1_MASK (~(15<<4)) +#define AW8695_BIT_WAVLOOP1_SEQ2_MASK (~(15<<0)) + +// WAVLOOP2: reg0x10 +#define AW8695_BIT_WAVLOOP2_SEQ3_MASK (~(15<<4)) +#define AW8695_BIT_WAVLOOP2_SEQ4_MASK (~(15<<0)) + +// WAVLOOP3: reg0x11 +#define AW8695_BIT_WAVLOOP3_SEQ5_MASK (~(15<<4)) +#define AW8695_BIT_WAVLOOP3_SEQ6_MASK (~(15<<0)) + +// WAVLOOP4: reg0x12 +#define AW8695_BIT_WAVLOOP4_SEQ7_MASK (~(15<<4)) +#define AW8695_BIT_WAVLOOP4_SEQ8_MASK (~(15<<0)) + + +// PLAYPRIO: reg0x1a +#define AW8695_BIT_PLAYPRIO_GO_MASK (~(3<<6)) +#define AW8695_BIT_PLAYPRIO_TRIG3_MASK (~(3<<4)) +#define AW8695_BIT_PLAYPRIO_TRIG2_MASK (~(3<<2)) +#define AW8695_BIT_PLAYPRIO_TRIG1_MASK (~(3<<0)) + +// TRGCFG1: reg0x1b +#define AW8695_BIT_TRGCFG1_TRG3_POLAR_MASK (~(1<<5)) +#define AW8695_BIT_TRGCFG1_TRG3_POLAR_NEG (1<<5) +#define AW8695_BIT_TRGCFG1_TRG3_POLAR_POS (0<<5) +#define AW8695_BIT_TRGCFG1_TRG3_EDGE_MASK (~(1<<4)) +#define AW8695_BIT_TRGCFG1_TRG3_EDGE_POS (1<<4) +#define AW8695_BIT_TRGCFG1_TRG3_EDGE_POS_NEG (0<<4) +#define AW8695_BIT_TRGCFG1_TRG2_POLAR_MASK (~(1<<3)) +#define AW8695_BIT_TRGCFG1_TRG2_POLAR_NEG (1<<3) +#define AW8695_BIT_TRGCFG1_TRG2_POLAR_POS (0<<3) +#define AW8695_BIT_TRGCFG1_TRG2_EDGE_MASK (~(1<<2)) +#define AW8695_BIT_TRGCFG1_TRG2_EDGE_POS (1<<2) +#define AW8695_BIT_TRGCFG1_TRG2_EDGE_POS_NEG (0<<2) +#define AW8695_BIT_TRGCFG1_TRG1_POLAR_MASK (~(1<<1)) +#define AW8695_BIT_TRGCFG1_TRG1_POLAR_NEG (1<<1) +#define AW8695_BIT_TRGCFG1_TRG1_POLAR_POS (0<<1) +#define AW8695_BIT_TRGCFG1_TRG1_EDGE_MASK (~(1<<0)) +#define AW8695_BIT_TRGCFG1_TRG1_EDGE_POS (1<<0) +#define AW8695_BIT_TRGCFG1_TRG1_EDGE_POS_NEG (0<<0) + +// TRGCFG2: reg0x1c +#define AW8695_BIT_TRGCFG2_TRG3_ENABLE_MASK (~(1<<2)) +#define AW8695_BIT_TRGCFG2_TRG3_ENABLE (1<<2) +#define AW8695_BIT_TRGCFG2_TRG3_DISABLE (0<<2) +#define AW8695_BIT_TRGCFG2_TRG2_ENABLE_MASK (~(1<<1)) +#define AW8695_BIT_TRGCFG2_TRG2_ENABLE (1<<1) +#define AW8695_BIT_TRGCFG2_TRG2_DISABLE (0<<1) +#define AW8695_BIT_TRGCFG2_TRG1_ENABLE_MASK (~(1<<0)) +#define AW8695_BIT_TRGCFG2_TRG1_ENABLE (1<<0) +#define AW8695_BIT_TRGCFG2_TRG1_DISABLE (0<<0) + +// DBGCTRL: reg0x20 +#define AW8695_BIT_DBGCTRL_INT_EDGE_MODE_MASK (~(1<<3)) +#define AW8695_BIT_DBGCTRL_INT_EDGE_MODE_POS (1<<3) +#define AW8695_BIT_DBGCTRL_INT_EDGE_MODE_BOTH (0<<3) +#define AW8695_BIT_DBGCTRL_INT_MODE_MASK (~(1<<2)) +#define AW8695_BIT_DBGCTRL_INT_MODE_EDGE (1<<2) +#define AW8695_BIT_DBGCTRL_INT_MODE_LEVEL (0<<2) + +// DATCTRL: reg0x2b +#define AW8695_BIT_DATCTRL_FC_MASK (~(1<<6)) +#define AW8695_BIT_DATCTRL_FC_1000HZ (3<<6) +#define AW8695_BIT_DATCTRL_FC_800HZ (3<<6) +#define AW8695_BIT_DATCTRL_FC_600HZ (1<<6) +#define AW8695_BIT_DATCTRL_FC_400HZ (0<<6) +#define AW8695_BIT_DATCTRL_LPF_ENABLE_MASK (~(1<<5)) +#define AW8695_BIT_DATCTRL_LPF_ENABLE (1<<5) +#define AW8695_BIT_DATCTRL_LPF_DISABLE (0<<5) +#define AW8695_BIT_DATCTRL_WAKEMODE_ENABLE_MASK (~(1<<0)) +#define AW8695_BIT_DATCTRL_WAKEMODE_ENABLE (1<<0) +#define AW8695_BIT_DATCTRL_WAKEMODE_DISABLE (0<<0) + +// PWMPRC: reg0x2d +#define AW8695_BIT_PWMPRC_PRC_MASK (~(1<<7)) +#define AW8695_BIT_PWMPRC_PRC_ENABLE (1<<7) +#define AW8695_BIT_PWMPRC_PRC_DISABLE (0<<7) +#define AW8695_BIT_PWMPRC_PRCTIME_MASK (~(0x7f<<0)) + +// PWMDBG: reg0x2e +#define AW8695_BIT_PWMDBG_PWM_MODE_MASK (~(3<<5)) +#define AW8695_BIT_PWMDBG_PWM_12K (3<<5) +#define AW8695_BIT_PWMDBG_PWM_24K (2<<5) +#define AW8695_BIT_PWMDBG_PWM_48K (0<<5) + +// BSTCFG: reg0x34 +#define AW8695_BIT_BSTCFG_PEAKCUR_MASK (~(7<<0)) +#define AW8695_BIT_BSTCFG_PEAKCUR_4A (7<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_3P75A (6<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_3P5A (5<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_3P25A (4<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_3A (3<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_2P5A (2<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_2A (1<<0) +#define AW8695_BIT_BSTCFG_PEAKCUR_1P5A (0<<0) + +// ANADBG: reg0x35 +#define AW8695_BIT_ANADBG_IOC_MASK (~(3<<2)) +#define AW8695_BIT_ANADBG_IOC_4P65A (3<<2) +#define AW8695_BIT_ANADBG_IOC_4P15A (2<<2) +#define AW8695_BIT_ANADBG_IOC_3P65A (1<<2) +#define AW8695_BIT_ANADBG_IOC_3P15A (0<<2) + +// ANACTRL: reg0x36 +#define AW8695_BIT_ANACTRL_LRA_SRC_MASK (~(1<<5)) +#define AW8695_BIT_ANACTRL_LRA_SRC_REG (1<<5) +#define AW8695_BIT_ANACTRL_LRA_SRC_EFUSE (0<<5) +#define AW8695_BIT_ANACTRL_HD_PD_MASK (~(1<<3)) +#define AW8695_BIT_ANACTRL_HD_PD_EN (1<<3) +#define AW8695_BIT_ANACTRL_HD_HZ_EN (0<<3) + +// BSTDBG4: reg0x3a +#define AW8695_BIT_BSTDBG4_BSTVOL_MASK (~(31<<1)) + +// PRLVL: reg0x3e +#define AW8695_BIT_PRLVL_PR_MASK (~(1<<7)) +#define AW8695_BIT_PRLVL_PR_ENABLE (1<<7) +#define AW8695_BIT_PRLVL_PR_DISABLE (0<<7) +#define AW8695_BIT_PRLVL_PRLVL_MASK (~(0x7f<<0)) + +//PRTIME: reg0x3f +#define AW8695_BIT_PRTIME_PRTIME_MASK (~(0xff<<0)) + +// BST_AUTO: reg0x47 +#define AW8695_BIT_BST_AUTO_BST_AUTOSW_MASK (~(1<<2)) +#define AW8695_BIT_BST_AUTO_BST_AUTOMATIC_BOOST (1<<2) +#define AW8695_BIT_BST_AUTO_BST_MANUAL_BOOST (0<<2) +#define AW8695_BIT_BST_AUTO_BST_RTP_MASK (~(1<<1)) +#define AW8695_BIT_BST_AUTO_BST_RTP_ENABLE (1<<1) +#define AW8695_BIT_BST_AUTO_BST_RTP_DISABLE (0<<1) +#define AW8695_BIT_BST_AUTO_BST_RAM_MASK (~(1<<0)) +#define AW8695_BIT_BST_AUTO_BST_RAM_ENABLE (1<<0) +#define AW8695_BIT_BST_AUTO_BST_RAM_DISABLE (0<<0) + +// CONT_CTRL: reg0x48 +#define AW8695_BIT_CONT_CTRL_ZC_DETEC_MASK (~(1<<7)) +#define AW8695_BIT_CONT_CTRL_ZC_DETEC_ENABLE (1<<7) +#define AW8695_BIT_CONT_CTRL_ZC_DETEC_DISABLE (0<<7) +#define AW8695_BIT_CONT_CTRL_WAIT_PERIOD_MASK (~(3<<5)) +#define AW8695_BIT_CONT_CTRL_WAIT_8PERIOD (3<<5) +#define AW8695_BIT_CONT_CTRL_WAIT_4PERIOD (2<<5) +#define AW8695_BIT_CONT_CTRL_WAIT_2PERIOD (1<<5) +#define AW8695_BIT_CONT_CTRL_WAIT_1PERIOD (0<<5) +#define AW8695_BIT_CONT_CTRL_MODE_MASK (~(1<<4)) +#define AW8695_BIT_CONT_CTRL_BY_DRV_TIME (1<<4) +#define AW8695_BIT_CONT_CTRL_BY_GO_SIGNAL (0<<4) +#define AW8695_BIT_CONT_CTRL_EN_CLOSE_MASK (~(1<<3)) +#define AW8695_BIT_CONT_CTRL_CLOSE_PLAYBACK (1<<3) +#define AW8695_BIT_CONT_CTRL_OPEN_PLAYBACK (0<<3) +#define AW8695_BIT_CONT_CTRL_F0_DETECT_MASK (~(1<<2)) +#define AW8695_BIT_CONT_CTRL_F0_DETECT_ENABLE (1<<2) +#define AW8695_BIT_CONT_CTRL_F0_DETECT_DISABLE (0<<2) +#define AW8695_BIT_CONT_CTRL_O2C_MASK (~(1<<1)) +#define AW8695_BIT_CONT_CTRL_O2C_ENABLE (1<<1) +#define AW8695_BIT_CONT_CTRL_O2C_DISABLE (0<<1) +#define AW8695_BIT_CONT_CTRL_AUTO_BRK_MASK (~(1<<0)) +#define AW8695_BIT_CONT_CTRL_AUTO_BRK_ENABLE (1<<0) +#define AW8695_BIT_CONT_CTRL_AUTO_BRK_DISABLE (0<<0) + +// D2SCFG: reg0x5e +#define AW8695_BIT_D2SCFG_CLK_ADC_MASK (~(7<<5)) +#define AW8695_BIT_D2SCFG_CLK_ASC_0P09375MHZ (7<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_0P1875MHZ (6<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_0P375MHZ (5<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_0P75MHZ (4<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_1P5MHZ (3<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_3MHZ (2<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_6MHZ (1<<5) +#define AW8695_BIT_D2SCFG_CLK_ASC_12MHZ (0<<5) + +// DETCTRL: reg0x5f +#define AW8695_BIT_DETCTRL_RL_OS_MASK (~(1<<6)) +#define AW8695_BIT_DETCTRL_RL_DETECT (1<<6) +#define AW8695_BIT_DETCTRL_OS_DETECT (0<<6) +#define AW8695_BIT_DETCTRL_PROTECT_MASK (~(1<<5)) +#define AW8695_BIT_DETCTRL_PROTECT_NO_ACTION (1<<5) +#define AW8695_BIT_DETCTRL_PROTECT_SHUTDOWN (0<<5) +#define AW8695_BIT_DETCTRL_ADO_SLOT_MODE_MASK (~(1<<4)) +#define AW8695_BIT_DETCTRL_ADO_SLOT_MODE_ENABLE (1<<4) +#define AW8695_BIT_DETCTRL_ADO_SLOT_MODE_DISABLE (0<<4) +#define AW8695_BIT_DETCTRL_VBAT_GO_MASK (~(1<<1)) +#define AW8695_BIT_DETCTRL_VABT_GO_ENABLE (1<<1) +#define AW8695_BIT_DETCTRL_VBAT_GO_DISBALE (0<<1) +#define AW8695_BIT_DETCTRL_DIAG_GO_MASK (~(1<<0)) +#define AW8695_BIT_DETCTRL_DIAG_GO_ENABLE (1<<0) +#define AW8695_BIT_DETCTRL_DIAG_GO_DISABLE (0<<0) + + +// ADCTEST: reg0x66 +#define AW8695_BIT_ADCTEST_VBAT_MODE_MASK (~(1<<6)) +#define AW8695_BIT_ADCTEST_VBAT_HW_COMP (1<<6) +#define AW8695_BIT_ADCTEST_VBAT_SW_COMP (0<<6) + +// BEMF_NUM: reg0x78 +#define AW8695_BIT_BEMF_NUM_BRK_MASK (~(15<<0)) + + #endif -- 2.20.1