treewide: Import OEM changes

Change-Id: I1375797d70876931eef62f215f70e2e4bc776d5b
This commit is contained in:
alk3pInjection
2022-09-17 17:12:03 +08:00
committed by Wiktor Rudzki
parent 1d1293e51d
commit 62ae18a846
10 changed files with 1193 additions and 7 deletions

View File

@@ -192,3 +192,8 @@
__tracepoint_rmnet_shs_low
__tracepoint_rmnet_shs_wq_high
__tracepoint_rmnet_shs_wq_low
device_remove_bin_file
snd_pcm_format_physical_width
snd_pcm_hw_constraint_mask64
devm_snd_soc_register_component
devm_gpio_free

View File

@@ -1016,6 +1016,10 @@ bool drm_mode_match(const struct drm_display_mode *mode1,
if (!mode1 || !mode2)
return false;
/* different refresh rate should be considered as different drm mode */
if (mode1->vrefresh != mode2->vrefresh)
return false;
if (match_flags & DRM_MODE_MATCH_TIMINGS &&
!drm_mode_match_timings(mode1, mode2))
return false;

View File

@@ -28,6 +28,13 @@
#include <linux/uaccess.h>
#include <linux/qpnp/qpnp-pbs.h>
#define RICHTAP_FOR_PMIC_ENABLE
#ifdef RICHTAP_FOR_PMIC_ENABLE
#include <linux/miscdevice.h>
#include <linux/mman.h>
#define RICHTAP_NAME "aw8697_haptic"
#endif //RICHTAP_FOR_PMIC_ENABLE
/* status register definitions in HAPTICS_CFG module */
#define HAP_CFG_REVISION2_REG 0x01
#define HAP_CFG_V1 0x1
@@ -441,6 +448,7 @@ struct haptics_effect {
struct brake_cfg *brake;
u32 id;
u32 vmax_mv;
u32 Vrms_mv;
u32 t_lra_us;
enum pattern_src src;
bool auto_res_disable;
@@ -471,6 +479,7 @@ struct haptics_play_info {
struct fifo_play_status fifo_status;
struct mutex lock;
u32 vmax_mv;
u32 Vrms_mv;
u32 length_us;
enum pattern_src pattern_src;
bool in_calibration;
@@ -479,6 +488,7 @@ struct haptics_play_info {
struct haptics_hw_config {
struct brake_cfg brake;
u32 vmax_mv;
u32 Vrms_mv;
u32 t_lra_us;
u32 cl_t_lra_us;
u32 lra_min_mohms;
@@ -498,6 +508,51 @@ struct custom_fifo_data {
u8 *data;
};
#ifdef RICHTAP_FOR_PMIC_ENABLE
enum {
RICHTAP_UNKNOWN = -1,
RICHTAP_AW_8697 = 0x05,
RICHTAP_PMIC_8350BH = 0x06,
};
enum {
MMAP_BUF_DATA_VALID = 0x55,
MMAP_BUF_DATA_FINISHED = 0xAA,
MMAP_BUF_DATA_INVALID = 0xFF,
};
#define RICHTAP_IOCTL_GROUP 0x52
#define RICHTAP_GET_HWINFO _IO(RICHTAP_IOCTL_GROUP, 0x03)
#define RICHTAP_SET_FREQ _IO(RICHTAP_IOCTL_GROUP, 0x04)
#define RICHTAP_SETTING_GAIN _IO(RICHTAP_IOCTL_GROUP, 0x05)
#define RICHTAP_OFF_MODE _IO(RICHTAP_IOCTL_GROUP, 0x06)
#define RICHTAP_TIMEOUT_MODE _IO(RICHTAP_IOCTL_GROUP, 0x07)
#define RICHTAP_RAM_MOD _IO(RICHTAP_IOCTL_GROUP, 0x08)
#define RICHTAP_RTP_MODE _IO(RICHTAP_IOCTL_GROUP, 0x09)
#define RICHTAP_STREAM_MODE _IO(RICHTAP_IOCTL_GROUP, 0x0A)
#define RICHTAP_UPDATE_RAM _IO(RICHTAP_IOCTL_GROUP, 0x10)
#define RICHTAP_GET_F0 _IO(RICHTAP_IOCTL_GROUP, 0x11)
#define RICHTAP_STOP_MODE _IO(RICHTAP_IOCTL_GROUP, 0x12)
#define RICHTAP_F0_UPDATE _IO(RICHTAP_IOCTL_GROUP, 0x13)
#define RICHTAP_MMAP_BUF_SIZE 1000
#define RICHTAP_MMAP_PAGE_ORDER 2
#define RICHTAP_MMAP_BUF_SUM 16
#pragma pack(4)
struct mmap_buf_format {
uint8_t status;
uint8_t bit;
int16_t length;
uint32_t reserve;
struct mmap_buf_format *kernel_next;
struct mmap_buf_format *user_next;
uint8_t data[RICHTAP_MMAP_BUF_SIZE];
};
#pragma pack()
#endif //RICHTAP_FOR_PMIC_ENABLE
struct haptics_chip {
struct device *dev;
struct regmap *regmap;
@@ -533,6 +588,16 @@ struct haptics_chip {
bool hpwr_vreg_enabled;
bool is_hv_haptics;
bool hboost_enabled;
#ifdef RICHTAP_FOR_PMIC_ENABLE
uint8_t *rtp_ptr;
struct mmap_buf_format *start_buf;
struct mmap_buf_format *current_buf;
struct work_struct richtap_stream_work;
struct work_struct richtap_erase_work;
int16_t pos;
atomic_t richtap_mode;
bool f0_flag;
#endif //RICHTAP_FOR_PMIC_ENABLE
};
struct haptics_reg_info {
@@ -540,6 +605,10 @@ struct haptics_reg_info {
u8 val;
};
#ifdef RICHTAP_FOR_PMIC_ENABLE
struct haptics_chip *g_richtap_ptr;
#endif //RICHTAP_FOR_PMIC_ENABLE
static inline int get_max_fifo_samples(struct haptics_chip *chip)
{
int val = 0;
@@ -1507,11 +1576,20 @@ static int haptics_open_loop_drive_config(struct haptics_chip *chip, bool en)
dev_dbg(chip->dev, "Toggle CAL_EN in open-loop-VREG playing\n");
}
#ifndef RICHTAP_FOR_PMIC_ENABLE
} else if (!is_haptics_external_powered(chip)) {
rc = haptics_masked_write(chip, chip->cfg_addr_base,
HAP_CFG_VSET_CFG_REG,
FORCE_VREG_RDY_BIT, 0);
}
#else
} else {
val = en ? FORCE_VREG_RDY_BIT : 0;
rc = haptics_masked_write(chip, chip->cfg_addr_base,
HAP_CFG_VSET_CFG_REG,
FORCE_VREG_RDY_BIT, val);
}
#endif //RICHTAP_FOR_PMIC_ENABLE
return rc;
}
@@ -2171,6 +2249,7 @@ static int haptics_init_custom_effect(struct haptics_chip *chip)
chip->custom_effect->t_lra_us = chip->config.t_lra_us;
chip->custom_effect->src = FIFO;
chip->custom_effect->auto_res_disable = true;
chip->custom_effect->Vrms_mv = chip->config.Vrms_mv;
return 0;
}
@@ -2841,17 +2920,31 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
struct haptics_chip *chip = data;
struct fifo_cfg *fifo;
struct fifo_play_status *status;
u32 samples_left;
u32 samples_left, fill;
u8 *samples, val;
int rc, num;
#ifdef RICHTAP_FOR_PMIC_ENABLE
int16_t num_rt = 0;
int16_t num_val = 0;
#endif //RICHTAP_FOR_PMIC_ENABLE
rc = haptics_read(chip, chip->cfg_addr_base,
HAP_CFG_INT_RT_STS_REG, &val, 1);
if (rc < 0)
return IRQ_HANDLED;
#ifdef RICHTAP_FOR_PMIC_ENABLE
if (!(val & FIFO_EMPTY_BIT)) {
haptics_get_fifo_fill_status(chip, &fill);
if ((atomic_read(&chip->richtap_mode)) && (fill < 24))
schedule_work(&chip->richtap_erase_work);
return IRQ_HANDLED;
}
#else
if (!(val & FIFO_EMPTY_BIT))
return IRQ_HANDLED;
#endif
mutex_lock(&chip->play.lock);
status = &chip->play.fifo_status;
@@ -2869,6 +2962,11 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
goto unlock;
}
#ifdef RICHTAP_FOR_PMIC_ENABLE
if (atomic_read(&chip->richtap_mode))
atomic_set(&chip->richtap_mode, false);
#endif //RICHTAP_FOR_PMIC_ENABLE
rc = haptics_stop_fifo_play(chip);
if (rc < 0)
goto unlock;
@@ -2880,6 +2978,72 @@ static irqreturn_t fifo_empty_irq_handler(int irq, void *data)
goto unlock;
}
#ifdef RICHTAP_FOR_PMIC_ENABLE
if (atomic_read(&chip->richtap_mode)) {
num_rt = (int16_t)haptics_get_available_fifo_memory(chip);
if (num_rt == get_max_fifo_samples(chip)) {
dev_dbg(chip->dev, "aacrichtap fifo stoped,wait next vibrator d%\n", num_rt);
goto unlock;
}
if (num_rt < 0) {
dev_err(chip->dev,"get fifo error, num_rt = %d\n", num_rt);
schedule_work(&chip->richtap_erase_work);
goto unlock;
}
while (num_rt > 0) {
num_val = chip->current_buf->length - chip->pos;
if (num_val < 0) {
dev_err(chip->dev,"aacrichtap length error , pos = %d, length = %d\n",
chip->pos, chip->current_buf->length);
schedule_work(&chip->richtap_erase_work);
goto unlock;
}
if ((chip->current_buf->status == MMAP_BUF_DATA_VALID)
&& (num_rt >= num_val)) {
samples_left = (u32)num_val;
samples_left -=
(samples_left % HAP_PTN_V2_FIFO_DIN_NUM);
rc = haptics_update_fifo_samples(chip,
&chip->current_buf->data[chip->pos], samples_left);
if (rc < 0) {
dev_err(chip->dev,"richtap Update fail, rc=%d\n", rc);
goto unlock;
}
num_rt -= num_val;
chip->current_buf->status = MMAP_BUF_DATA_INVALID;
chip->current_buf->length = 0;
chip->current_buf = chip->current_buf->kernel_next;
chip->pos = 0;
continue;
}
if (chip->current_buf->status == MMAP_BUF_DATA_VALID) {
num_rt -= (num_rt % HAP_PTN_V2_FIFO_DIN_NUM);
rc = haptics_update_fifo_samples(chip,
&chip->current_buf->data[chip->pos], (u32)num_rt);
if (rc < 0) {
dev_err(chip->dev,
"richtap Update FIFO fail, rc=%d\n", rc);
goto unlock;
}
chip->pos += num_rt;
num_rt = 0;
continue;
}
if (chip->current_buf->status != MMAP_BUF_DATA_FINISHED)
dev_err(chip->dev, "aac richtap invalid data buf\n");
schedule_work(&chip->richtap_erase_work);
dev_dbg(chip->dev,"richtap stream mode is done\n");
break;
}
goto unlock;
}
#endif //RICHTAP_FOR_PMIC_ENABLE
if (!chip->play.effect)
goto unlock;
@@ -4094,6 +4258,15 @@ static int haptics_parse_dt(struct haptics_chip *chip)
goto free_pbs;
}
config->Vrms_mv = DEFAULT_VMAX_MV;
of_property_read_u32(node, "qcom,Vrms_mv", &config->Vrms_mv);
if (config->Vrms_mv >= MAX_VMAX_MV) {
dev_err(chip->dev, "qcom,Vrms_mv (%d) exceed the max value: %d\n",
config->Vrms_mv, MAX_VMAX_MV);
rc = -EINVAL;
goto free_pbs;
}
config->fifo_empty_thresh = get_fifo_empty_threshold(chip);
of_property_read_u32(node, "qcom,fifo-empty-threshold",
&config->fifo_empty_thresh);
@@ -4453,7 +4626,7 @@ static int haptics_detect_lra_frequency(struct haptics_chip *chip)
{
int rc;
u8 autores_cfg, amplitude;
u32 vmax_mv = chip->config.vmax_mv;
u32 vmax_mv = chip->config.Vrms_mv;
rc = haptics_read(chip, chip->cfg_addr_base,
HAP_CFG_AUTORES_CFG_REG, &autores_cfg, 1);
@@ -4636,10 +4809,566 @@ static ssize_t lra_impedance_show(struct class *c,
}
static CLASS_ATTR_RO(lra_impedance);
static ssize_t fifo_vmax_store(struct class *c,
struct class_attribute *attr, const char *buf, size_t count)
{
struct haptics_chip *chip = container_of(c,
struct haptics_chip, hap_class);
u32 bt;
ssize_t result;
result = sscanf(buf, "%d", &bt);
if (result != 1)
return -EINVAL;
chip->config.vmax_mv = bt;
return count;
}
static ssize_t fifo_vmax_show(struct class *c,
struct class_attribute *attr, char *buf)
{
struct haptics_chip *chip = container_of(c,
struct haptics_chip, hap_class);
u32 cl_f_lra;
cl_f_lra = chip->config.vmax_mv;
return scnprintf(buf, PAGE_SIZE, "%dmv\n", cl_f_lra);
}
static CLASS_ATTR_RW(fifo_vmax);
#ifdef RICHTAP_FOR_PMIC_ENABLE
static void richtap_clean_buf(struct haptics_chip *chip, int status)
{
struct mmap_buf_format *opbuf = chip->start_buf;
int i;
for (i = 0; i < RICHTAP_MMAP_BUF_SUM; i++) {
opbuf->status = status;
opbuf->length = 0;
opbuf = opbuf->kernel_next;
}
}
static int richtap_get_lra_frequency_hz(struct haptics_chip *chip, u32 *val)
{
if (chip->config.cl_t_lra_us == 0)
return -EINVAL;
*val = USEC_PER_SEC / chip->config.cl_t_lra_us;
#ifdef raac_FEATURE_CHG_BASIC
if (chip->cal_data_restore) {
if (chip->cal_data.cl_t_lra_us != 0)
*val = USEC_PER_SEC / chip->cal_data.cl_t_lra_us;
else
*val = 0;
dev_err(chip->dev, "lra_frequency_hz read : %d\n", *val);
}
#endif
return 0;
}
static int richtap_rc_clk_disable(struct haptics_chip *chip)
{
int rc;
u8 val;
/*
* All other playing modes would use AUTO mode RC
* calibration except FIFO streaming mode, so restore
* back to AUTO RC calibration after FIFO playing.
*/
val = CAL_RC_CLK_DISABLED_VAL << CAL_RC_CLK_SHIFT;
rc = haptics_masked_write(chip, chip->cfg_addr_base,
HAP_CFG_CAL_EN_REG, CAL_RC_CLK_MASK, val);
if (rc < 0)
return rc;
return 0;
}
static int richtap_set_fifo(struct haptics_chip *chip, struct fifo_cfg *fifo)
{
struct fifo_play_status *status = &chip->play.fifo_status;
u32 num, fifo_thresh;
int rc, available;
if (atomic_read(&status->is_busy) == 1) {
dev_err(chip->dev, "FIFO is busy\n");
return -EBUSY;
}
if (chip->ptn_revision == HAP_PTN_V1 &&
fifo->period_per_s > F_8KHZ &&
fifo->num_s > get_max_fifo_samples(chip)) {
dev_err(chip->dev, "PM8350B v1 not play long pattern higher than 8 KHz play rate\n");
return -EINVAL;
}
/* Configure FIFO play rate */
rc = haptics_set_fifo_playrate(chip, fifo->period_per_s);
if (rc < 0)
return rc;
atomic_set(&status->written_done, 0);
atomic_set(&status->cancelled, 0);
status->samples_written = 0;
/*
* Write the 1st set of the data into FIFO if there are
* more than get_max_fifo_samples samples, the rest will be
* written if any FIFO memory is available after playing.
*/
num = min_t(u32, fifo->num_s, get_max_fifo_samples(chip));
available = haptics_get_available_fifo_memory(chip);
if (available < 0)
return available;
num = min_t(u32, available, num);
rc = haptics_update_fifo_samples(chip, fifo->samples, num);
if (rc < 0) {
dev_err(chip->dev, "write FIFO samples failed, rc=%d\n", rc);
return rc;
}
dev_dbg(chip->dev, "aac Richtap set busy to 1\n");
atomic_set(&status->is_busy, 1);
status->samples_written = num;
fifo_thresh = 480; //480 * 40us
/*
* Set FIFO empty threshold here. FIFO empty IRQ will
* be enabled after playing FIFO samples so that more
* FIFO samples can be written (if available) when
* FIFO empty IRQ is triggered.
*/
return haptics_set_fifo_empty_threshold(chip, fifo_thresh);
}
static void richtap_erase_work_proc(struct work_struct *work)
{
struct haptics_chip *chip = container_of(work,
struct haptics_chip, richtap_erase_work);
int rc;
u8 count = 5;
u32 fill;
while (count--) {
rc = haptics_get_fifo_fill_status(chip, &fill);
if ((rc < 0) || (atomic_read(&chip->play.fifo_status.is_busy) == 0))
return;
if (fill < 24)
break;
fill /= 24; //24k play_rate_hz
fill *= 1000;
usleep_range((fill + 25), (fill + 30));
}
dev_dbg(chip->dev, "aacrichtap0424 fill=%d,count = %d\n", fill, count);
mutex_lock(&chip->play.lock);
richtap_clean_buf(chip, MMAP_BUF_DATA_FINISHED);
atomic_set(&chip->play.fifo_status.written_done, 1);
haptics_set_fifo_empty_threshold(chip, 0);
haptics_stop_fifo_play(chip);
atomic_set(&chip->richtap_mode, false);
mutex_unlock(&chip->play.lock);
}
static int richtap_playback(struct haptics_chip *chip, bool on)
{
struct haptics_play_info *play = &chip->play;
int rc;
if (on) {
rc = haptics_enable_play(chip, true);
if (rc < 0)
return rc;
if (play->pattern_src == FIFO)
haptics_fifo_empty_irq_config(chip, true);
} else {
if (play->pattern_src == FIFO &&
atomic_read(&play->fifo_status.is_busy)) {
dev_dbg(chip->dev, "FIFO playing is not done yet, defer stopping in erase\n");
return 0;
}
rc = haptics_enable_play(chip, false);
}
return rc;
}
static int richtap_load_prebake(struct haptics_chip *chip, u8 *data, u32 length)
{
struct haptics_play_info *play = &chip->play;
struct custom_fifo_data custom_data = {};
struct fifo_cfg *fifo;
int rc;
if (!chip->custom_effect || !chip->custom_effect->fifo)
return -ENOMEM;
fifo = chip->custom_effect->fifo;
custom_data.length = length;
custom_data.play_rate_hz = 24000; //24000;
custom_data.data = data;
dev_dbg(chip->dev, "aac RichTap data %d length\n", length);
rc = haptics_convert_sample_period(chip, custom_data.play_rate_hz);
if (rc < 0) {
dev_err(chip->dev, "aac RichTap Can't support play rate: %d Hz\n",
custom_data.play_rate_hz);
return rc;
}
mutex_lock(&chip->play.lock);
fifo->period_per_s = rc;
fifo->num_s = length;
/*
* Before allocating samples buffer, free the old sample
* buffer first if it's not been freed.
*/
kfree(fifo->samples);
fifo->samples = kcalloc(custom_data.length, sizeof(u8), GFP_KERNEL);
if (!fifo->samples) {
rc = -ENOMEM;
goto unlock;
}
memcpy(fifo->samples, custom_data.data, custom_data.length);
play->effect = chip->custom_effect;
play->brake = NULL;
rc = haptics_set_vmax_mv(chip, play->vmax_mv);
if (rc < 0)
goto cleanup;
rc = haptics_enable_autores(chip, false);
if (rc < 0)
goto cleanup;
//Toggle HAPTICS_EN for a clear start point of FIFO playing
rc = haptics_toggle_module_enable(chip);
if (rc < 0)
goto cleanup;
play->pattern_src = FIFO;
rc = richtap_set_fifo(chip, play->effect->fifo);
if (rc < 0)
goto cleanup;
dev_dbg(chip->dev, "aac RichTap haptics_set_fifo success\n");
mutex_unlock(&chip->play.lock);
return 0;
cleanup:
kfree(fifo->samples);
fifo->samples = NULL;
unlock:
mutex_unlock(&chip->play.lock);
return rc;
}
static void richtap_work_proc(struct work_struct *work)
{
struct haptics_chip *chip = container_of(work, struct haptics_chip, richtap_stream_work);
struct mmap_buf_format *first;
uint32_t count = 100;
int ret;
while ((count--) && (chip->start_buf->status != MMAP_BUF_DATA_VALID)) {
usleep_range(1000, 1001);
}
if ((chip->start_buf->length <= 0) ||
(chip->start_buf->status != MMAP_BUF_DATA_VALID)) {
dev_err(chip->dev, "aacrichtap first length invalid %d %d ",
chip->start_buf->status, chip->start_buf->length);
mutex_lock(&chip->play.lock);
richtap_clean_buf(chip, MMAP_BUF_DATA_FINISHED);
atomic_set(&chip->play.fifo_status.written_done, 1);
haptics_set_fifo_empty_threshold(chip, 0);
haptics_stop_fifo_play(chip);
atomic_set(&chip->richtap_mode, false);
mutex_unlock(&chip->play.lock);
return;
}
chip->pos = 0;
first = chip->start_buf;
if (first->length >= get_max_fifo_samples(chip)) {
if ((first->length > get_max_fifo_samples(chip))) {
chip->pos = get_max_fifo_samples(chip);
chip->current_buf = first;
} else {
chip->current_buf = first->kernel_next;
}
goto play_rate;
} else {
chip->current_buf = first->kernel_next;
}
count = 0;
while (first->length < get_max_fifo_samples(chip)) {
if ((chip->current_buf->status == MMAP_BUF_DATA_FINISHED) ||
(count > 30))
break;
if ((chip->current_buf->status != MMAP_BUF_DATA_VALID) &&
(count < 30)) {
count++;
usleep_range(1000, 1001);
dev_err(chip->dev, "wait for data\n");
continue;
}
if ((first->length + chip->current_buf->length) <=
get_max_fifo_samples(chip)) {
memcpy(&first->data[first->length], chip->current_buf->data,
chip->current_buf->length);
chip->current_buf->status = MMAP_BUF_DATA_INVALID;
first->length += chip->current_buf->length;
chip->current_buf->length = 0;
chip->current_buf = chip->current_buf->kernel_next;
count = 0;
} else {
memcpy(&first->data[first->length], chip->current_buf->data,
(get_max_fifo_samples(chip) - first->length));
chip->pos = get_max_fifo_samples(chip) - first->length;
first->length = get_max_fifo_samples(chip);
dev_err(chip->dev, "first full\n");
}
}
play_rate:
dev_dbg(chip->dev, "pos %d,first %d,current %d\n", chip->pos, first->length, chip->current_buf->length);
ret = richtap_load_prebake(chip, first->data, first->length <=
get_max_fifo_samples(chip) ? first->length : get_max_fifo_samples(chip));
if (ret < 0) {
dev_err(chip->dev, "aac RichTap Upload FIFO data fail\n", ret);
return;
}
if (first->length <= get_max_fifo_samples(chip)) {
first->status = MMAP_BUF_DATA_INVALID;
first->length = 0;
}
ret = haptics_enable_hpwr_vreg(chip, true);
if (ret < 0) {
dev_err(chip->dev, "aac RichTap en hpwr_vreg fail, rc=%d\n", ret);
return;
}
ret = haptics_wait_hboost_ready(chip);
if (ret < 0) {
schedule_work(&chip->richtap_erase_work);
return;
}
ret = richtap_playback(chip, true);
if (ret < 0)
dev_err(chip->dev, "aac RichTap richtap_playback fail, rc=%d\n", ret);
}
/*****************************************************
*
* haptic fops
*
*****************************************************/
static int richtap_file_open(struct inode *inode, struct file *file)
{
if (!try_module_get(THIS_MODULE))
return -ENODEV;
file->private_data = (void *)g_richtap_ptr;
return 0;
}
static int richtap_file_release(struct inode *inode, struct file *file)
{
file->private_data = (void *)NULL;
module_put(THIS_MODULE);
return 0;
}
static long richtap_file_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct haptics_chip *chip = (struct haptics_chip *)file->private_data;
uint32_t tmp;
int ret = 0;
dev_dbg(chip->dev, "%s: cmd=0x%x, arg=0x%lx\n",
__func__, cmd, arg);
switch (cmd) {
case RICHTAP_GET_HWINFO:
tmp = RICHTAP_AW_8697;
if (copy_to_user((void __user *)arg, &tmp, sizeof(uint32_t)))
return -EFAULT;
break;
case RICHTAP_RTP_MODE:
if (copy_from_user(chip->rtp_ptr, (void __user *)arg,
RICHTAP_MMAP_BUF_SIZE * RICHTAP_MMAP_BUF_SUM)) {
ret = -EFAULT;
break;
}
tmp = *((uint32_t *)chip->rtp_ptr);
if (tmp > (RICHTAP_MMAP_BUF_SIZE * RICHTAP_MMAP_BUF_SUM - 4)) {
dev_err(chip->dev, "aac RichTap rtp mode date len error %d\n", tmp);
ret = -EINVAL;
break;
}
mutex_lock(&chip->play.lock);
haptics_stop_fifo_play(chip);
mutex_unlock(&chip->play.lock);
richtap_rc_clk_disable(chip);
atomic_set(&chip->richtap_mode, false);
ret = richtap_load_prebake(chip, &chip->rtp_ptr[4], tmp);
if (ret < 0) {
dev_err(chip->dev, "aac RichTap Upload FIFO data fail\n", ret);
break;
}
ret = haptics_enable_hpwr_vreg(chip, true);
if (ret < 0) {
dev_err(chip->dev, "aac RichTap en hpwr_vreg fail, rc=%d\n", ret);
break;
}
ret = haptics_wait_hboost_ready(chip);
if (ret < 0) {
schedule_work(&chip->richtap_erase_work);
break;
}
ret = richtap_playback(chip, true);
if (ret < 0)
dev_err(chip->dev, "aac RichTap en hpwr_vreg fail, rc=%d\n", ret);
schedule_work(&chip->richtap_erase_work);
break;
case RICHTAP_OFF_MODE:
break;
case RICHTAP_GET_F0:
ret = richtap_get_lra_frequency_hz(chip, &tmp);
dev_dbg(chip->dev, "aac RichTap get f0 =%d\n", tmp);
//tmp = 170; //just for debug,f0 right should remove
if (ret < 0) {
dev_err(chip->dev, "aac RichTap get f0 error, ret=%d\n", ret);
break;
}
tmp *= 10;
if (copy_to_user((void __user *)arg, &tmp, sizeof(uint32_t)))
ret = -EFAULT;
break;
case RICHTAP_SETTING_GAIN:
if (arg > 0x80)
arg = 0x80;
tmp = chip->config.vmax_mv;
chip->play.vmax_mv = ((u32)(arg * tmp)) / 128;
haptics_set_vmax_mv(chip, chip->play.vmax_mv);
break;
case RICHTAP_STREAM_MODE:
richtap_clean_buf(chip, MMAP_BUF_DATA_INVALID);
mutex_lock(&chip->play.lock);
haptics_stop_fifo_play(chip);
mutex_unlock(&chip->play.lock);
richtap_rc_clk_disable(chip);
atomic_set(&chip->richtap_mode, true);
schedule_work(&chip->richtap_stream_work);
break;
case RICHTAP_STOP_MODE:
mutex_lock(&chip->play.lock);
richtap_clean_buf(chip, MMAP_BUF_DATA_FINISHED);
atomic_set(&chip->play.fifo_status.written_done, 1);
haptics_set_fifo_empty_threshold(chip, 0);
haptics_stop_fifo_play(chip);
atomic_set(&chip->richtap_mode, false);
mutex_unlock(&chip->play.lock);
break;
case RICHTAP_F0_UPDATE:
break;
default:
dev_err(chip->dev, "%s, unknown cmd\n", __func__);
break;
}
return ret;
}
static ssize_t richtap_file_read(struct file *filp, char *buff, size_t len, loff_t *offset)
{
return len;
}
static ssize_t richtap_file_write(struct file *filp, const char *buff, size_t len, loff_t *off)
{
return len;
}
static int richtap_file_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct haptics_chip *chip = (struct haptics_chip *)filp->private_data;
unsigned long phys;
int ret = 0;
//only accept PROT_READ, PROT_WRITE and MAP_SHARED from the API of mmap
vm_flags_t vm_flags = calc_vm_prot_bits(PROT_READ|PROT_WRITE, 0) |
calc_vm_flag_bits(MAP_SHARED);
vm_flags |= current->mm->def_flags | VM_MAYREAD |
VM_MAYWRITE | VM_MAYEXEC | VM_SHARED | VM_MAYSHARE;
if (vma && (pgprot_val(vma->vm_page_prot) != pgprot_val(vm_get_page_prot(vm_flags))))
return -EPERM;
if (vma && ((vma->vm_end - vma->vm_start) != (PAGE_SIZE << RICHTAP_MMAP_PAGE_ORDER)))
return -ENOMEM;
phys = virt_to_phys(chip->start_buf);
ret = remap_pfn_range(vma, vma->vm_start, (phys >> PAGE_SHIFT),
(vma->vm_end - vma->vm_start), vma->vm_page_prot);
if (ret) {
dev_err(chip->dev, "Error mmap failed\n");
return ret;
}
return ret;
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
.read = richtap_file_read,
.write = richtap_file_write,
.mmap = richtap_file_mmap,
.unlocked_ioctl = richtap_file_unlocked_ioctl,
.open = richtap_file_open,
.release = richtap_file_release,
};
static struct miscdevice richtap_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = RICHTAP_NAME,
.fops = &fops,
};
#endif //RICHTAP_FOR_PMIC_ENABLE
static struct attribute *hap_class_attrs[] = {
&class_attr_lra_calibration.attr,
&class_attr_lra_frequency_hz.attr,
&class_attr_lra_impedance.attr,
&class_attr_fifo_vmax.attr,
NULL,
};
ATTRIBUTE_GROUPS(hap_class);
@@ -4723,6 +5452,8 @@ static int haptics_probe(struct platform_device *pdev)
rc = devm_request_threaded_irq(chip->dev, chip->fifo_empty_irq,
NULL, fifo_empty_irq_handler,
IRQF_ONESHOT, "fifo-empty", chip);
dev_err(chip->dev, "request fifo-empty IRQ success, rc=%d\n",
rc);
if (rc < 0) {
dev_err(chip->dev, "request fifo-empty IRQ failed, rc=%d\n",
rc);
@@ -4782,12 +5513,51 @@ static int haptics_probe(struct platform_device *pdev)
goto destroy_ff;
}
#ifdef RICHTAP_FOR_PMIC_ENABLE
chip->rtp_ptr = kmalloc(RICHTAP_MMAP_BUF_SIZE * RICHTAP_MMAP_BUF_SUM, GFP_KERNEL);
if (chip->rtp_ptr == NULL)
goto destroy_ff;
chip->start_buf = (struct mmap_buf_format *)__get_free_pages(GFP_KERNEL,
RICHTAP_MMAP_PAGE_ORDER);
if (chip->start_buf == NULL) {
dev_err(chip->dev, "Error __get_free_pages failed\n");
goto destroy_richtap;
}
SetPageReserved(virt_to_page(chip->start_buf));
{
struct mmap_buf_format *temp;
uint32_t i = 0;
temp = chip->start_buf;
for (i = 1; i < RICHTAP_MMAP_BUF_SUM; i++) {
temp->kernel_next = (chip->start_buf + i);
temp = temp->kernel_next;
}
temp->kernel_next = chip->start_buf;
}
INIT_WORK(&chip->richtap_stream_work, richtap_work_proc);
INIT_WORK(&chip->richtap_erase_work, richtap_erase_work_proc);
misc_register(&richtap_misc);
atomic_set(&chip->richtap_mode, false);
g_richtap_ptr = chip;
#endif //RICHTAP_FOR_PMIC_ENABLE
#ifdef CONFIG_DEBUG_FS
rc = haptics_create_debugfs(chip);
if (rc < 0)
dev_err(chip->dev, "Creating debugfs failed, rc=%d\n", rc);
#endif
return 0;
#ifdef RICHTAP_FOR_PMIC_ENABLE
destroy_richtap:
kfree(chip->rtp_ptr);
#endif //RICHTAP_FOR_PMIC_ENABLE
destroy_ff:
input_ff_destroy(chip->input_dev);
return rc;
@@ -4804,6 +5574,12 @@ static int haptics_remove(struct platform_device *pdev)
#ifdef CONFIG_DEBUG_FS
debugfs_remove_recursive(chip->debugfs_dir);
#endif
#ifdef RICHTAP_FOR_PMIC_ENABLE
kfree(chip->rtp_ptr);
free_pages((unsigned long)chip->start_buf, RICHTAP_MMAP_PAGE_ORDER);
#endif //RICHTAP_FOR_PMIC_ENABLE
input_ff_destroy(chip->input_dev);
dev_set_drvdata(chip->dev, NULL);

View File

@@ -7,7 +7,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
int msm_show_resume_irq_mask;
int msm_show_resume_irq_mask = 1;
module_param_named(
debug_mask, msm_show_resume_irq_mask, int, 0664);

View File

@@ -35,7 +35,7 @@
#define CLASS_NAME "nfc"
// NFC character device name, this will be in /dev/
#define NFC_CHAR_DEV_NAME "nq-nci"
#define NFC_CHAR_DEV_NAME "pn553"
// HDR length of NCI packet
#define NCI_HDR_LEN 3
@@ -82,7 +82,7 @@
// Ioctls
// The type should be aligned with MW HAL definitions
#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, unsigned int)
#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, long)
#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, unsigned int)
#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, unsigned int)
#define NFC_GET_PLATFORM_TYPE _IO(NFC_MAGIC, 0x04)

View File

@@ -258,6 +258,27 @@ out:
return ret;
}
static ssize_t scan_stats_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nfc_dev *nfc_dev = dev_get_drvdata(dev);
int value;
value = gpio_get_value(nfc_dev->gpio.clkreq);
return scnprintf(buf, PAGE_SIZE,"%d\n", value);
}
static DEVICE_ATTR_RO(scan_stats);
static struct attribute *nfc_i2c_attrs[] = {
&dev_attr_scan_stats.attr,
NULL,
};
static struct attribute_group nfc_i2c_attr_grp = {
.attrs = nfc_i2c_attrs,
};
static const struct file_operations nfc_i2c_dev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -372,6 +393,12 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto err_nfcc_hw_check;
}
ret = sysfs_create_group(&client->dev.kobj, &nfc_i2c_attr_grp);
if (ret) {
pr_err("%s: sysfs_create_group failed\n", __func__);
goto err_nfcc_hw_check;
}
device_init_wakeup(&client->dev, true);
i2c_dev->irq_wake_up = false;
nfc_dev->is_ese_session_active = false;

View File

@@ -1808,7 +1808,7 @@ static const struct msm_pingroup yupik_groups[] = {
};
static const int yupik_reserved_gpios[] = {
32, 33, 48, 49, 50, 51, -1
32, 33, -1
};
static struct pinctrl_qup yupik_qup_regs[] = {
QUP_I3C(0, QUP_I3C_0_MODE_OFFSET),

View File

@@ -12,6 +12,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/rpmsg.h>
@@ -53,6 +54,10 @@
#define WLS_FW_BUF_SIZE 128
#define DEFAULT_RESTRICT_FCC_UA 1000000
#define CONFIG_STWLC38_FW
#define DIVIDE_1000_TIMES 1000
#define DIVIDE_1000000_TIMES 1000000
enum usb_connector_type {
USB_CONNECTOR_TYPE_TYPEC,
USB_CONNECTOR_TYPE_MICRO_USB,
@@ -115,6 +120,11 @@ enum usb_property_id {
USB_TYPEC_COMPLIANT,
USB_SCOPE,
USB_CONNECTOR_TYPE,
USB_CHARGE_PUMP_ENABLE,
USB_CC_ORIENTATION,
USB_CHARGE_ENABLE,
USB_SLOWCHARGE_ENABLE,
USB_CHARGE_POWER,
USB_PROP_MAX,
};
@@ -126,6 +136,13 @@ enum wireless_property_id {
WLS_CURR_MAX,
WLS_TYPE,
WLS_BOOST_EN,
#ifdef CONFIG_STWLC38_FW
WLS_VOLT_TX,
WLS_CURR_TX,
WLS_ST38_REG,
WLS_ST38_DATA,
WLS_REVERSE_STATUS,
#endif
WLS_PROP_MAX,
};
@@ -243,6 +260,7 @@ struct battery_chg_dev {
int fake_soc;
bool block_tx;
bool ship_mode_en;
bool usb_charger_en;
bool debug_battery_detected;
bool wls_fw_update_reqd;
u32 wls_fw_version;
@@ -321,6 +339,7 @@ static const char * const qc_power_supply_usb_type_text[] = {
"HVDCP", "HVDCP_3", "HVDCP_3P5"
};
#ifndef CONFIG_STWLC38_FW
static int battery_chg_fw_write(struct battery_chg_dev *bcdev, void *data,
int len)
{
@@ -346,6 +365,7 @@ static int battery_chg_fw_write(struct battery_chg_dev *bcdev, void *data,
return rc;
}
#endif
static int battery_chg_write(struct battery_chg_dev *bcdev, void *data,
int len)
@@ -1269,6 +1289,7 @@ static void battery_chg_subsys_up_work(struct work_struct *work)
}
}
#ifndef CONFIG_STWLC38_FW
static int wireless_fw_send_firmware(struct battery_chg_dev *bcdev,
const struct firmware *fw)
{
@@ -1313,6 +1334,7 @@ static int wireless_fw_send_firmware(struct battery_chg_dev *bcdev,
return 0;
}
#endif
static int wireless_fw_check_for_update(struct battery_chg_dev *bcdev,
u32 version, size_t size)
@@ -1333,6 +1355,60 @@ static int wireless_fw_check_for_update(struct battery_chg_dev *bcdev,
#define IDT_FW_MAJOR_VER_OFFSET 0x94
#define IDT_FW_MINOR_VER_OFFSET 0x96
#ifdef CONFIG_STWLC38_FW
static int wireless_fw_update(struct battery_chg_dev *bcdev, bool force)
{
struct psy_state *pst;
u32 version = 0;
int rc;
pm_stay_awake(bcdev->dev);
/*
* Check for USB presence. If nothing is connected, check whether
* battery SOC is at least 50% before allowing FW update.
*/
pst = &bcdev->psy_list[PSY_TYPE_USB];
rc = read_property_id(bcdev, pst, USB_ONLINE);
if (rc < 0)
goto out;
if (!pst->prop[USB_ONLINE]) {
pst = &bcdev->psy_list[PSY_TYPE_BATTERY];
rc = read_property_id(bcdev, pst, BATT_CAPACITY);
if (rc < 0)
goto out;
if ((pst->prop[BATT_CAPACITY] / 100) < 50) {
pr_err("Battery SOC should be at least 50%% or connect charger\n");
rc = -EINVAL;
goto out;
}
}
pr_err("Wireless FW update start\n");
rc = wireless_fw_check_for_update(bcdev, version, 0);
if (rc < 0) {
pr_err("Wireless FW update not needed, rc=%d\n", rc);
goto release_fw;
}
if (!bcdev->wls_fw_update_reqd) {
pr_warn("Wireless FW update not required\n");
goto release_fw;
}
pr_err("Wireless FW update done\n");
release_fw:
bcdev->wls_fw_crc = 0;
out:
pm_relax(bcdev->dev);
return rc;
}
#else
static int wireless_fw_update(struct battery_chg_dev *bcdev, bool force)
{
const struct firmware *fw;
@@ -1433,6 +1509,7 @@ out:
return rc;
}
#endif
static ssize_t wireless_fw_crc_store(struct class *c,
struct class_attribute *attr,
@@ -1764,6 +1841,120 @@ static ssize_t soh_show(struct class *c, struct class_attribute *attr,
}
static CLASS_ATTR_RO(soh);
static ssize_t charge_pump_enable_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
int rc;
rc = read_property_id(bcdev, pst, USB_CHARGE_PUMP_ENABLE);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[USB_CHARGE_PUMP_ENABLE]);
}
static CLASS_ATTR_RO(charge_pump_enable);
static ssize_t typec_cc_orientation_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
int rc;
rc = read_property_id(bcdev, pst, USB_CC_ORIENTATION);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[USB_CC_ORIENTATION]);
}
static CLASS_ATTR_RO(typec_cc_orientation);
static ssize_t usb_charger_en_store(struct class *c, struct class_attribute *attr,
const char *buf, size_t count)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
int rc;
bool val;
if (kstrtobool(buf, &val))
return -EINVAL;
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_USB],
USB_CHARGE_ENABLE, val);
if (rc < 0)
return rc;
return count;
}
static ssize_t usb_charger_en_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
int rc;
rc = read_property_id(bcdev, pst, USB_CHARGE_ENABLE);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[USB_CHARGE_ENABLE]);
}
static CLASS_ATTR_RW(usb_charger_en);
static ssize_t charge_power_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
read_property_id(bcdev, pst, USB_CHARGE_POWER);
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[USB_CHARGE_POWER]);
}
static CLASS_ATTR_RO(charge_power);
static ssize_t slowcharge_en_store(struct class *c, struct class_attribute *attr,
const char *buf, size_t count)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
int rc;
u32 val;
if (kstrtou32(buf, 16, &val))
return -EINVAL;
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_USB],
USB_SLOWCHARGE_ENABLE, val);
if (rc < 0)
return rc;
return count;
}
static ssize_t slowcharge_en_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
int rc;
rc = read_property_id(bcdev, pst, USB_SLOWCHARGE_ENABLE);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[USB_SLOWCHARGE_ENABLE]);
}
static CLASS_ATTR_RW(slowcharge_en);
static ssize_t ship_mode_en_store(struct class *c, struct class_attribute *attr,
const char *buf, size_t count)
{
@@ -1786,6 +1977,106 @@ static ssize_t ship_mode_en_show(struct class *c, struct class_attribute *attr,
}
static CLASS_ATTR_RW(ship_mode_en);
#ifdef CONFIG_STWLC38_FW
static ssize_t wls_volt_tx_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_WLS];
int rc;
rc = read_property_id(bcdev, pst, WLS_VOLT_TX);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[WLS_VOLT_TX]);
}
static CLASS_ATTR_RO(wls_volt_tx);
static ssize_t wls_curr_tx_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_WLS];
int rc;
rc = read_property_id(bcdev, pst, WLS_CURR_TX);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "%d\n", pst->prop[WLS_CURR_TX]);
}
static CLASS_ATTR_RO(wls_curr_tx);
static ssize_t wls_st38_reg_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_WLS];
int rc;
rc = read_property_id(bcdev, pst, WLS_ST38_REG);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "0x%04x\n", pst->prop[WLS_ST38_REG]);
}
static ssize_t wls_st38_reg_store(struct class *c,
struct class_attribute *attr,
const char *buf, size_t count)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
int rc;
u32 val;
if (kstrtou32(buf, 16, &val))
return -EINVAL;
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_WLS],
WLS_ST38_REG, val);
if (rc < 0)
return rc;
return count;
}
static CLASS_ATTR_RW(wls_st38_reg);
static ssize_t wls_st38_data_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_WLS];
int rc;
rc = read_property_id(bcdev, pst, WLS_ST38_DATA);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "0x%04x; %d\n", pst->prop[WLS_ST38_DATA], pst->prop[WLS_ST38_DATA]);
}
static ssize_t wls_st38_data_store(struct class *c,
struct class_attribute *attr,
const char *buf, size_t count)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
int rc;
u32 val;
if (kstrtou32(buf, 0, &val))
return -EINVAL;
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_WLS],
WLS_ST38_DATA, val);
if (rc < 0)
return rc;
return count;
}
static CLASS_ATTR_RW(wls_st38_data);
static ssize_t wls_reverse_status_show(struct class *c, struct class_attribute *attr,
char *buf)
{
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
battery_class);
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_WLS];
int rc;
rc = read_property_id(bcdev, pst, WLS_REVERSE_STATUS);
if (rc < 0)
return rc;
return scnprintf(buf, PAGE_SIZE, "0x%x\n", pst->prop[WLS_REVERSE_STATUS]);
}
static CLASS_ATTR_RO(wls_reverse_status);
#endif
static ssize_t charging_enabled_store(struct class *c,
struct class_attribute *attr,
const char *buf, size_t count)
@@ -1847,10 +2138,25 @@ static struct attribute *battery_class_attrs[] = {
&class_attr_wireless_fw_version.attr,
&class_attr_wireless_fw_crc.attr,
&class_attr_ship_mode_en.attr,
&class_attr_usb_charger_en.attr,
&class_attr_charge_power.attr,
&class_attr_slowcharge_en.attr,
&class_attr_usb_charger_en.attr,
&class_attr_charge_power.attr,
&class_attr_slowcharge_en.attr,
&class_attr_restrict_chg.attr,
&class_attr_restrict_cur.attr,
&class_attr_usb_real_type.attr,
&class_attr_usb_typec_compliant.attr,
&class_attr_charge_pump_enable.attr,
&class_attr_typec_cc_orientation.attr,
#ifdef CONFIG_STWLC38_FW
&class_attr_wls_volt_tx.attr,
&class_attr_wls_curr_tx.attr,
&class_attr_wls_st38_reg.attr,
&class_attr_wls_st38_data.attr,
&class_attr_wls_reverse_status.attr,
#endif
&class_attr_charging_enabled.attr,
NULL,
};

View File

@@ -17,6 +17,7 @@
#define FSA4480_SWITCH_SETTINGS 0x04
#define FSA4480_SWITCH_CONTROL 0x05
#define FSA4480_SWITCH_STATUS 0X06
#define FSA4480_SWITCH_STATUS1 0x07
#define FSA4480_SLOW_L 0x08
#define FSA4480_SLOW_R 0x09
@@ -27,6 +28,9 @@
#define FSA4480_DELAY_L_MIC 0x0E
#define FSA4480_DELAY_L_SENSE 0x0F
#define FSA4480_DELAY_L_AGND 0x10
#define FSA4480_FUNCTION_ENABLE 0X12
#define FSA4480_JACK_STATUS 0X17
#define FSA4480_JACK_FLAG 0X18
#define FSA4480_RESET 0x1E
struct fsa4480_priv {
@@ -227,6 +231,7 @@ static int fsa4480_usbc_analog_setup_switches_ucsi(
{
int rc = 0;
int mode;
int value = 0;
struct device *dev;
if (!fsa_priv)
@@ -241,12 +246,58 @@ static int fsa4480_usbc_analog_setup_switches_ucsi(
dev_dbg(dev, "%s: setting GPIOs active = %d\n",
__func__, mode != TYPEC_ACCESSORY_NONE);
regmap_write(fsa_priv->regmap, FSA4480_RESET, 0x01);
msleep(1);
switch (mode) {
/* add all modes FSA should notify for in here */
case TYPEC_ACCESSORY_AUDIO:
/* activate switches */
fsa4480_usbc_update_settings(fsa_priv, 0x00, 0x9F);
regmap_read(fsa_priv->regmap, 0x00, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x00]=0x%x\n",__func__, value);
if (value == 241) {
dev_dbg(fsa_priv->dev, "%s:DIO headset detection .\n",__func__);
regmap_write(fsa_priv->regmap, FSA4480_SLOW_L, 0x4f);
regmap_read(fsa_priv->regmap, FSA4480_SLOW_L, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x08]=0x%x\n",__func__, value);
regmap_write(fsa_priv->regmap, FSA4480_SLOW_R, 0x4f);
regmap_read(fsa_priv->regmap, FSA4480_SLOW_R, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x09]=0x%x\n",__func__, value);
regmap_write(fsa_priv->regmap, FSA4480_SLOW_MIC, 0x4f);
regmap_read(fsa_priv->regmap, FSA4480_SLOW_MIC, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x0a]=0x%x\n",__func__, value);
regmap_write(fsa_priv->regmap, FSA4480_SLOW_SENSE, 0x4f);
regmap_read(fsa_priv->regmap, FSA4480_SLOW_SENSE, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x0b]=0x%x\n",__func__, value);
regmap_write(fsa_priv->regmap, FSA4480_SLOW_GND, 0x4f);
regmap_read(fsa_priv->regmap, FSA4480_SLOW_GND, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x0c]=0x%x\n",__func__, value);
regmap_write(fsa_priv->regmap, FSA4480_FUNCTION_ENABLE, 0x09);
dev_dbg(fsa_priv->dev, "%s: set reg[0x12] done.\n",__func__);
regmap_read(fsa_priv->regmap, FSA4480_FUNCTION_ENABLE, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x12]=0x%x\n",__func__, value);
msleep(1000);
regmap_read(fsa_priv->regmap, FSA4480_JACK_FLAG, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x18]=0x%x\n",__func__, value);
msleep(1);
regmap_read(fsa_priv->regmap, FSA4480_JACK_STATUS, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x17]=0x%x\n",__func__, value);
regmap_read(fsa_priv->regmap, FSA4480_SWITCH_STATUS, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x6]=0x%x\n",__func__, value);
regmap_read(fsa_priv->regmap, FSA4480_SWITCH_STATUS1, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x7]=0x%x\n",__func__, value);
} else {
dev_dbg(fsa_priv->dev, "%s:FSA headset detection.\n",__func__);
fsa4480_usbc_update_settings(fsa_priv, 0x00, 0x9F);
regmap_write(fsa_priv->regmap, FSA4480_FUNCTION_ENABLE, 0x01);
dev_dbg(fsa_priv->dev, "%s: set reg[0x12] done.\n",__func__);
regmap_read(fsa_priv->regmap, FSA4480_JACK_STATUS, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x17]=0x%x\n",__func__, value);
regmap_read(fsa_priv->regmap, FSA4480_SWITCH_STATUS, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x6]=0x%x\n",__func__, value);
regmap_read(fsa_priv->regmap, FSA4480_SWITCH_STATUS1, &value);
dev_dbg(fsa_priv->dev, "%s: reg[0x7]=0x%x\n",__func__, value);
}
/* notify call chain on event */
blocking_notifier_call_chain(&fsa_priv->fsa4480_notifier,
@@ -259,6 +310,8 @@ static int fsa4480_usbc_analog_setup_switches_ucsi(
/* deactivate switches */
fsa4480_usbc_update_settings(fsa_priv, 0x18, 0x98);
regmap_write(fsa_priv->regmap, FSA4480_FUNCTION_ENABLE, 0x00);
dev_dbg(fsa_priv->dev, "%s: set reg[0x12] reset.\n",__func__);
break;
default:
/* ignore other usb connection modes */
@@ -538,6 +591,9 @@ static int fsa4480_remove(struct i2c_client *i2c)
if (!fsa_priv)
return -EINVAL;
regmap_write(fsa_priv->regmap, FSA4480_FUNCTION_ENABLE, 0x00);
dev_dbg(fsa_priv->dev, "%s: set reg[0x12] reset.\n",__func__);
if (fsa_priv->use_powersupply) {
/* deregister from PMI */
power_supply_unreg_notifier(&fsa_priv->nb);

View File

@@ -731,6 +731,17 @@ out:
return ret;
}
void icnss_mac2bd(u8 *localAddr)
{
int i;
u8 temp;
for (i = 0; i < 3; i++) {
temp = localAddr[i];
localAddr[i] = localAddr[5-i];
localAddr[5-i] = temp;
}
}
int icnss_qmi_get_dms_mac(struct icnss_priv *priv)
{
struct dms_get_mac_address_req_msg_v01 req;
@@ -789,6 +800,7 @@ int icnss_qmi_get_dms_mac(struct icnss_priv *priv)
}
priv->dms.mac_valid = true;
memcpy(priv->dms.mac, resp.mac_address, QMI_WLFW_MAC_ADDR_SIZE_V01);
icnss_mac2bd(priv->dms.mac);
icnss_pr_info("Received DMS MAC: [%pM]\n", priv->dms.mac);
out:
return ret;