treewide: Import OEM changes
Change-Id: I1375797d70876931eef62f215f70e2e4bc776d5b
This commit is contained in:
committed by
Wiktor Rudzki
parent
1d1293e51d
commit
62ae18a846
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user