techpack: audio: aw88261: Load calibration file through firmware class
Direct access to filesystem is insane and hits a neverallow, load it through the firmware class instead. Co-authored-by: Michael Bestas <mkbestas@lineageos.org> Change-Id: Ic522644c73d63a36430526736257d635deb08f6a
This commit is contained in:
1 parent
fd2f1845d4
commit
b25b68201f
3 files changed
+35
-59
No files matched your search
@@ -20,6 +20,7 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <sound/core.h>
|
#include <sound/core.h>
|
||||||
@@ -47,20 +48,12 @@ static unsigned int g_cali_status = false;
|
|||||||
static struct miscdevice *g_misc_dev = NULL;
|
static struct miscdevice *g_misc_dev = NULL;
|
||||||
static DEFINE_MUTEX(g_cali_lock);
|
static DEFINE_MUTEX(g_cali_lock);
|
||||||
|
|
||||||
#ifdef AW_CALI_STORE_EXAMPLE
|
#define AWINIC_CALI_FILE "aw_cali.bin"
|
||||||
/*write cali to persist file example*/
|
|
||||||
#define AWINIC_CALI_FILE "/mnt/vendor/persist/factory/audio/aw_cali.bin"
|
|
||||||
#define AW_INT_DEC_DIGIT 10
|
#define AW_INT_DEC_DIGIT 10
|
||||||
|
|
||||||
static void aw_fs_read(struct file *file, char *buf, size_t count, loff_t *pos)
|
#ifdef AW_CALI_STORE_EXAMPLE
|
||||||
{
|
/*write cali to persist file example*/
|
||||||
#ifdef AW_KERNEL_VER_OVER_5_4_0
|
#define AWINIC_CALI_PERSIST_FILE "/mnt/vendor/persist/factory/audio/aw_cali.bin"
|
||||||
kernel_read(file, buf, count, pos);
|
|
||||||
#else
|
|
||||||
vfs_read(file, buf, count, pos);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void aw_fs_write(struct file *file, char *buf, size_t count, loff_t *pos)
|
static void aw_fs_write(struct file *file, char *buf, size_t count, loff_t *pos)
|
||||||
{
|
{
|
||||||
#ifdef AW_KERNEL_VER_OVER_5_4_0
|
#ifdef AW_KERNEL_VER_OVER_5_4_0
|
||||||
@@ -77,7 +70,7 @@ static int aw_cali_write_cali_re_to_file(int32_t cali_re, int channel)
|
|||||||
loff_t pos = 0;
|
loff_t pos = 0;
|
||||||
mm_segment_t fs;
|
mm_segment_t fs;
|
||||||
|
|
||||||
fp = filp_open(AWINIC_CALI_FILE, O_RDWR | O_CREAT, 0644);
|
fp = filp_open(AWINIC_CALI_PERSIST_FILE, O_RDWR | O_CREAT, 0644);
|
||||||
if (IS_ERR(fp)) {
|
if (IS_ERR(fp)) {
|
||||||
pr_err("%s:channel:%d open %s failed!\n",
|
pr_err("%s:channel:%d open %s failed!\n",
|
||||||
__func__, channel, AWINIC_CALI_FILE);
|
__func__, channel, AWINIC_CALI_FILE);
|
||||||
@@ -101,60 +94,49 @@ static int aw_cali_write_cali_re_to_file(int32_t cali_re, int channel)
|
|||||||
filp_close(fp, NULL);
|
filp_close(fp, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int aw_cali_get_read_cali_re(int32_t *cali_re, int channel)
|
static int aw_cali_get_read_cali_re(struct aw_device *aw_dev, int32_t *cali_re, int channel)
|
||||||
{
|
{
|
||||||
struct file *fp = NULL;
|
int rc = -EINVAL;
|
||||||
/*struct inode *node;*/
|
|
||||||
int f_size;
|
|
||||||
char *buf = NULL;
|
|
||||||
int32_t int_cali_re = 0;
|
int32_t int_cali_re = 0;
|
||||||
loff_t pos = 0;
|
loff_t pos = 0;
|
||||||
mm_segment_t fs;
|
const struct firmware *fw = NULL;
|
||||||
|
|
||||||
fp = filp_open(AWINIC_CALI_FILE, O_RDONLY, 0);
|
/* open cali file */
|
||||||
if (IS_ERR(fp)) {
|
if (request_firmware(&fw, AWINIC_CALI_FILE, aw_dev->dev)) {
|
||||||
pr_err("%s:channel:%d open %s failed!\n",
|
pr_err("%s:channel:%d open %s failed!\n",
|
||||||
__func__, channel, AWINIC_CALI_FILE);
|
__func__, channel, AWINIC_CALI_FILE);
|
||||||
return -EINVAL;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fw || !fw->data || !fw->size) {
|
||||||
|
pr_err("%s: invalid firmware", __func__);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fw->size < AW_INT_DEC_DIGIT || fw->size > AW_INT_DEC_DIGIT * 2) {
|
||||||
|
pr_err("%s: invalid firmware size\n", __func__);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = AW_INT_DEC_DIGIT * channel;
|
pos = AW_INT_DEC_DIGIT * channel;
|
||||||
|
|
||||||
/*node = fp->f_dentry->d_inode;*/
|
if (sscanf(fw->data + pos, "%d", &int_cali_re) == 1)
|
||||||
/*f_size = node->i_size;*/
|
|
||||||
f_size = AW_INT_DEC_DIGIT;
|
|
||||||
|
|
||||||
buf = kzalloc(f_size + 1, GFP_ATOMIC);
|
|
||||||
if (!buf) {
|
|
||||||
pr_err("%s: channel:%d malloc mem %d failed!\n",
|
|
||||||
__func__, channel, f_size);
|
|
||||||
filp_close(fp, NULL);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs = get_fs();
|
|
||||||
set_fs(KERNEL_DS);
|
|
||||||
|
|
||||||
aw_fs_read(fp, buf, f_size, &pos);
|
|
||||||
|
|
||||||
set_fs(fs);
|
|
||||||
|
|
||||||
if (sscanf(buf, "%d", &int_cali_re) == 1)
|
|
||||||
*cali_re = int_cali_re;
|
*cali_re = int_cali_re;
|
||||||
else
|
else
|
||||||
*cali_re = AW_ERRO_CALI_VALUE;
|
*cali_re = AW_ERRO_CALI_VALUE;
|
||||||
|
|
||||||
pr_info("%s: channel:%d buf:%s int_cali_re: %d\n",
|
pr_info("%s: channel:%d int_cali_re: %d\n",
|
||||||
__func__, channel, buf, int_cali_re);
|
__func__, channel, int_cali_re);
|
||||||
|
|
||||||
kfree(buf);
|
rc = 0;
|
||||||
buf = NULL;
|
|
||||||
filp_close(fp, NULL);
|
|
||||||
|
|
||||||
return 0;
|
error:
|
||||||
|
/* close file */
|
||||||
|
release_firmware(fw);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*custom need add to set/get cali_re form/to nv*/
|
/*custom need add to set/get cali_re form/to nv*/
|
||||||
int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
|
int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
|
||||||
@@ -170,18 +152,14 @@ int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int aw_cali_read_re_from_nvram(int32_t *cali_re, int32_t channel)
|
int aw_cali_read_re_from_nvram(struct aw_device *aw_dev, int32_t *cali_re, int32_t channel)
|
||||||
{
|
{
|
||||||
/*custom add, if success return value is 0 , else -1*/
|
/*custom add, if success return value is 0 , else -1*/
|
||||||
#ifdef AW_CALI_STORE_EXAMPLE
|
|
||||||
if (channel >= AW_DEV_CH_MAX) {
|
if (channel >= AW_DEV_CH_MAX) {
|
||||||
pr_err("%s: unsupported channel [%d] \n", __func__, channel);
|
pr_err("%s: unsupported channel [%d] \n", __func__, channel);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return aw_cali_get_read_cali_re(cali_re, channel);
|
return aw_cali_get_read_cali_re(aw_dev, cali_re, channel);
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int aw_cali_store_cali_re(struct aw_device *aw_dev, int32_t re)
|
int aw_cali_store_cali_re(struct aw_device *aw_dev, int32_t re)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#ifndef __AWINIC_CALIBRATION_H__
|
#ifndef __AWINIC_CALIBRATION_H__
|
||||||
#define __AWINIC_CALIBRATION_H__
|
#define __AWINIC_CALIBRATION_H__
|
||||||
|
|
||||||
#define AW_CALI_STORE_EXAMPLE
|
|
||||||
|
|
||||||
#define AW_CALI_READ_TIMES (3)
|
#define AW_CALI_READ_TIMES (3)
|
||||||
#define AW_ERRO_CALI_VALUE (0)
|
#define AW_ERRO_CALI_VALUE (0)
|
||||||
#define AW_CALI_RE_DEFAULT_TIMER (3000)
|
#define AW_CALI_RE_DEFAULT_TIMER (3000)
|
||||||
@@ -136,7 +134,7 @@ struct aw_cali_desc {
|
|||||||
int aw_cali_init(struct aw_cali_desc *cali_desc);
|
int aw_cali_init(struct aw_cali_desc *cali_desc);
|
||||||
void aw_cali_deinit(struct aw_cali_desc *cali_desc);
|
void aw_cali_deinit(struct aw_cali_desc *cali_desc);
|
||||||
int aw_cali_svc_get_cali_status(void);
|
int aw_cali_svc_get_cali_status(void);
|
||||||
int aw_cali_read_re_from_nvram(int32_t *cali_re, int32_t ch_index);
|
int aw_cali_read_re_from_nvram(struct aw_device *aw_dev, int32_t *cali_re, int32_t ch_index);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1509,7 +1509,7 @@ int aw_dev_init_cali_re(struct aw_device *aw_dev)
|
|||||||
|
|
||||||
if (aw_dev->cali_desc.mode) {
|
if (aw_dev->cali_desc.mode) {
|
||||||
if (aw_dev->cali_desc.cali_re == AW_ERRO_CALI_VALUE) {
|
if (aw_dev->cali_desc.cali_re == AW_ERRO_CALI_VALUE) {
|
||||||
ret = aw_cali_read_re_from_nvram(&aw_dev->cali_desc.cali_re, aw_dev->channel);
|
ret = aw_cali_read_re_from_nvram(aw_dev, &aw_dev->cali_desc.cali_re, aw_dev->channel);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
aw_dev_info(aw_dev->dev, "read nvram cali failed, use default Re");
|
aw_dev_info(aw_dev->dev, "read nvram cali failed, use default Re");
|
||||||
aw_dev->cali_desc.cali_re = AW_ERRO_CALI_VALUE;
|
aw_dev->cali_desc.cali_re = AW_ERRO_CALI_VALUE;
|
||||||
|
|||||||
Reference in new issue
Block a user