565 lines
14 KiB
C
Executable file
565 lines
14 KiB
C
Executable file
/*
|
|
* Copyright (C) 2014-2020 NXP Semiconductors, All Rights Reserved.
|
|
* Copyright 2020-2021 GOODIX, All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
*/
|
|
|
|
#include "inc/tfa_sysfs.h"
|
|
|
|
#define TFA_STC_DEV_NAME "tfa_stc"
|
|
#define FILESIZE_STC (10)
|
|
|
|
#if defined(TFA_ENABLE_STC_TUNING)
|
|
#define FILESIZE_STC_TUNING (100)
|
|
#endif
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
#if defined(TFA_ENABLE_STC_TUNING)
|
|
static ssize_t spkt_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t spkt_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(spkt);
|
|
|
|
static ssize_t sknt_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t sknt_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(sknt);
|
|
|
|
#if defined(TFA_STEREO_NODE)
|
|
static ssize_t spkt_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t spkt_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(spkt_r);
|
|
|
|
static ssize_t sknt_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t sknt_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(sknt_r);
|
|
#endif /* TFA_STEREO_NODE */
|
|
|
|
#if defined(TFA_USE_STC_VOLUME_TABLE)
|
|
static ssize_t minmax_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t minmax_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(minmax);
|
|
|
|
static ssize_t gtable_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t gtable_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(gtable);
|
|
|
|
#if defined(TFA_STEREO_NODE)
|
|
static ssize_t minmax_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t minmax_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(minmax_r);
|
|
|
|
static ssize_t gtable_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf);
|
|
static ssize_t gtable_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size);
|
|
static DEVICE_ATTR_RW(gtable_r);
|
|
#endif /* TFA_STEREO_NODE */
|
|
#endif /* TFA_USE_STC_VOLUME_TABLE */
|
|
|
|
static struct attribute *tfa_stc_attr[] = {
|
|
&dev_attr_spkt.attr,
|
|
&dev_attr_sknt.attr,
|
|
#if defined(TFA_STEREO_NODE)
|
|
&dev_attr_spkt_r.attr,
|
|
&dev_attr_sknt_r.attr,
|
|
#endif /* TFA_STEREO_NODE */
|
|
#if defined(TFA_USE_STC_VOLUME_TABLE)
|
|
&dev_attr_minmax.attr,
|
|
&dev_attr_gtable.attr,
|
|
#if defined(TFA_STEREO_NODE)
|
|
&dev_attr_minmax_r.attr,
|
|
&dev_attr_gtable_r.attr,
|
|
#endif /* TFA_STEREO_NODE */
|
|
#endif /* TFA_USE_STC_VOLUME_TABLE */
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group tfa_stc_attr_grp = {
|
|
.attrs = tfa_stc_attr,
|
|
};
|
|
#endif /* TFA_ENABLE_STC_TUNING */
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
#if defined(TFA_ENABLE_STC_TUNING)
|
|
static struct device *tfa_stc_dev;
|
|
#endif
|
|
|
|
static int sknt_data[MAX_HANDLES];
|
|
|
|
/* ---------------------------------------------------------------------- */
|
|
|
|
#if defined(TFA_ENABLE_STC_TUNING)
|
|
static ssize_t update_sknt_control(int idx, char *buf)
|
|
{
|
|
struct tfa_device *tfa = NULL;
|
|
int size;
|
|
char sknt_result[FILESIZE_STC] = {0};
|
|
|
|
tfa = tfa98xx_get_tfa_device_from_index(0);
|
|
if (tfa == NULL)
|
|
return -EINVAL; /* unused device */
|
|
|
|
if (idx < 0 || idx >= tfa->dev_count)
|
|
return -EINVAL;
|
|
|
|
snprintf(sknt_result, FILESIZE_STC,
|
|
"%d", sknt_data[idx]);
|
|
|
|
if (sknt_result[0] == 0)
|
|
size = snprintf(buf, 7 + 1, "no_data"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(sknt_result) + 1,
|
|
"%s", sknt_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t spkt_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_0;
|
|
int value, size;
|
|
char spkt_result[FILESIZE_STC] = {0};
|
|
|
|
value = tfa98xx_update_spkt_data(idx);
|
|
pr_info("%s: tfa_stc - dev %d - speaker temperature (%d)\n",
|
|
__func__, idx, value);
|
|
|
|
snprintf(spkt_result, FILESIZE_STC,
|
|
"%d", value);
|
|
|
|
if (spkt_result[0] == 0)
|
|
size = snprintf(buf, 1 + 1, "0"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(spkt_result) + 1,
|
|
"%s", spkt_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t spkt_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
pr_info("%s: dev %d - not allowed to write speaker temperature\n",
|
|
__func__, INDEX_0);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t sknt_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_0;
|
|
int ret;
|
|
|
|
ret = update_sknt_control(idx, buf);
|
|
if (ret > 0)
|
|
pr_info("%s: tfa_stc - dev %d - surface temperature (%d)\n",
|
|
__func__, idx, sknt_data[idx]);
|
|
else
|
|
pr_err("%s: tfa_stc dev %d - error %d\n",
|
|
__func__, idx, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t sknt_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
int idx = INDEX_0;
|
|
int ret;
|
|
int value = 0;
|
|
|
|
ret = kstrtou32(buf, 10, &value);
|
|
if (!value) {
|
|
pr_info("%s: do nothing\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = tfa98xx_write_sknt_control(idx, value);
|
|
if (!ret) {
|
|
pr_info("%s: tfa_stc - dev %d - surface temperature (%d)\n",
|
|
__func__, idx, value);
|
|
sknt_data[idx] = value;
|
|
} else {
|
|
pr_err("%s: tfa_stc dev %d - error %d\n",
|
|
__func__, idx, ret);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
#if defined(TFA_USE_STC_VOLUME_TABLE)
|
|
static ssize_t minmax_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_0;
|
|
int size = 0;
|
|
int stc_min = 0, stc_max = 0;
|
|
char minmax_result[FILESIZE_STC_TUNING] = {0};
|
|
|
|
stc_min = tfa_get_stc_minmax(idx, 0);
|
|
stc_max = tfa_get_stc_minmax(idx, 1);
|
|
|
|
snprintf(minmax_result, FILESIZE_STC_TUNING,
|
|
"%d %d", stc_min, stc_max);
|
|
|
|
if (minmax_result[0] == 0)
|
|
size = snprintf(buf, 7 + 1, "no_data"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(minmax_result) + 1,
|
|
"%s", minmax_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
pr_info("%s: tfa_stc - dev %d - (min %d, max %d)\n",
|
|
__func__, idx, stc_min, stc_max);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t minmax_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
int idx = INDEX_0;
|
|
int ret = 0;
|
|
int mint = 0, maxt = 0;
|
|
|
|
ret = sscanf(buf, "%d %d", &mint, &maxt);
|
|
if (ret < 2) {
|
|
pr_info("%s: do nothing\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
tfa_set_stc_minmax(idx, 0, mint);
|
|
tfa_set_stc_minmax(idx, 1, maxt);
|
|
pr_info("%s: tfa_stc - dev %d - (min %d, max %d)\n",
|
|
__func__, idx, mint, maxt);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t gtable_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_0;
|
|
int i, size = 0;
|
|
char gtable_result[FILESIZE_STC_TUNING] = {0};
|
|
int vol_table[STC_TABLE_MAX] = {0};
|
|
|
|
tfa_get_stc_gtable(idx, vol_table);
|
|
|
|
snprintf(gtable_result, FILESIZE_STC_TUNING,
|
|
"%d %d %d %d %d %d %d %d %d %d",
|
|
vol_table[0], vol_table[1],
|
|
vol_table[2], vol_table[3],
|
|
vol_table[4], vol_table[5],
|
|
vol_table[6], vol_table[7],
|
|
vol_table[8], vol_table[9]);
|
|
|
|
if (gtable_result[0] == 0)
|
|
size = snprintf(buf, 7 + 1, "no_data"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(gtable_result) + 1,
|
|
"%s", gtable_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < STC_TABLE_MAX; i++)
|
|
pr_info("%s: tfa_stc - dev %d - gain[%d]=%d\n",
|
|
__func__, idx, i, vol_table[i]);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t gtable_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
int idx = INDEX_0;
|
|
int i, ret = 0;
|
|
int value[STC_TABLE_MAX] = {0};
|
|
|
|
ret = sscanf(buf, "%d %d %d %d %d %d %d %d %d %d",
|
|
&value[0], &value[1], &value[2], &value[3], &value[4],
|
|
&value[5], &value[6], &value[7], &value[8], &value[9]);
|
|
if (ret < STC_TABLE_MAX) {
|
|
pr_info("%s: do nothing\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
tfa_set_stc_gtable(idx, value);
|
|
|
|
for (i = 0; i < STC_TABLE_MAX; i++) {
|
|
pr_info("%s: tfa_stc - dev %d - gain[%d]=%d\n",
|
|
__func__, idx, i, value[i]);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
#endif /* TFA_USE_STC_VOLUME_TABLE */
|
|
|
|
#if defined(TFA_STEREO_NODE)
|
|
static ssize_t spkt_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_1;
|
|
int value, size;
|
|
char spkt_result[FILESIZE_STC] = {0};
|
|
|
|
value = tfa98xx_update_spkt_data(idx);
|
|
pr_info("%s: tfa_stc - dev %d - speaker temperature (%d)\n",
|
|
__func__, idx, value);
|
|
|
|
snprintf(spkt_result, FILESIZE_STC,
|
|
"%d", value);
|
|
|
|
if (spkt_result[0] == 0)
|
|
size = snprintf(buf, 1 + 1, "0"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(spkt_result) + 1,
|
|
"%s", spkt_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t spkt_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
pr_info("%s: dev %d - not allowed to write speaker temperature\n",
|
|
__func__, INDEX_1);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t sknt_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_1;
|
|
int ret;
|
|
|
|
ret = update_sknt_control(idx, buf);
|
|
if (ret > 0)
|
|
pr_info("%s: tfa_stc - dev %d - surface temperature (%d)\n",
|
|
__func__, idx, sknt_data[idx]);
|
|
else
|
|
pr_err("%s: tfa_stc dev %d - error %d\n",
|
|
__func__, idx, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t sknt_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
int idx = INDEX_1;
|
|
int ret;
|
|
int value = 0;
|
|
|
|
ret = kstrtou32(buf, 10, &value);
|
|
if (!value) {
|
|
pr_info("%s: do nothing\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = tfa98xx_write_sknt_control(idx, value);
|
|
if (!ret) {
|
|
pr_info("%s: tfa_stc - dev %d - surface temperature (%d)\n",
|
|
__func__, idx, value);
|
|
sknt_data[idx] = value;
|
|
} else {
|
|
pr_err("%s: tfa_stc dev %d - error %d\n",
|
|
__func__, idx, ret);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
#if defined(TFA_USE_STC_VOLUME_TABLE)
|
|
static ssize_t minmax_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_1;
|
|
int size = 0;
|
|
int stc_min = 0, stc_max = 0;
|
|
char minmax_result[FILESIZE_STC_TUNING] = {0};
|
|
|
|
stc_min = tfa_get_stc_minmax(idx, 0);
|
|
stc_max = tfa_get_stc_minmax(idx, 1);
|
|
|
|
snprintf(minmax_result, FILESIZE_STC_TUNING,
|
|
"%d %d", stc_min, stc_max);
|
|
|
|
if (minmax_result[0] == 0)
|
|
size = snprintf(buf, 7 + 1, "no_data"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(minmax_result) + 1,
|
|
"%s", minmax_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
pr_info("%s: tfa_stc - dev %d - (min %d, max %d)\n",
|
|
__func__, idx, stc_min, stc_max);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t minmax_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
int idx = INDEX_1;
|
|
int ret = 0;
|
|
int mint = 0, maxt = 0;
|
|
|
|
ret = sscanf(buf, "%d %d", &mint, &maxt);
|
|
if (ret < 2) {
|
|
pr_info("%s: do nothing\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
tfa_set_stc_minmax(idx, 0, mint);
|
|
tfa_set_stc_minmax(idx, 1, maxt);
|
|
pr_info("%s: tfa_stc - dev %d - (min %d, max %d)\n",
|
|
__func__, idx, mint, maxt);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t gtable_r_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
int idx = INDEX_1;
|
|
int i, size = 0;
|
|
char gtable_result[FILESIZE_STC_TUNING] = {0};
|
|
int vol_table[STC_TABLE_MAX] = {0};
|
|
|
|
tfa_get_stc_gtable(idx, vol_table);
|
|
|
|
snprintf(gtable_result, FILESIZE_STC_TUNING,
|
|
"%d %d %d %d %d %d %d %d %d %d",
|
|
vol_table[0], vol_table[1],
|
|
vol_table[2], vol_table[3],
|
|
vol_table[4], vol_table[5],
|
|
vol_table[6], vol_table[7],
|
|
vol_table[8], vol_table[9]);
|
|
|
|
if (gtable_result[0] == 0)
|
|
size = snprintf(buf, 7 + 1, "no_data"); /* no data */
|
|
else
|
|
size = snprintf(buf, strlen(gtable_result) + 1,
|
|
"%s", gtable_result);
|
|
|
|
if (size <= 0) {
|
|
pr_err("%s: tfa_stc failed to show in sysfs file\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < STC_TABLE_MAX; i++)
|
|
pr_info("%s: tfa_stc - dev %d - gain[%d]=%d\n",
|
|
__func__, idx, i, vol_table[i]);
|
|
|
|
return size;
|
|
}
|
|
|
|
static ssize_t gtable_r_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t size)
|
|
{
|
|
int idx = INDEX_1;
|
|
int i, ret = 0;
|
|
int value[STC_TABLE_MAX] = {0};
|
|
|
|
ret = sscanf(buf, "%d %d %d %d %d %d %d %d %d %d",
|
|
&value[0], &value[1], &value[2], &value[3], &value[4],
|
|
&value[5], &value[6], &value[7], &value[8], &value[9]);
|
|
if (ret < STC_TABLE_MAX) {
|
|
pr_info("%s: do nothing\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
tfa_set_stc_gtable(idx, value);
|
|
|
|
for (i = 0; i < STC_TABLE_MAX; i++) {
|
|
pr_info("%s: tfa_stc - dev %d - gain[%d]=%d\n",
|
|
__func__, idx, i, value[i]);
|
|
}
|
|
|
|
return size;
|
|
}
|
|
#endif /* TFA_USE_STC_VOLUME_TABLE */
|
|
#endif /* TFA_STEREO_NODE */
|
|
#endif /* TFA_ENABLE_STC_TUNING */
|
|
|
|
int tfa98xx_stc_init(struct class *tfa_class)
|
|
{
|
|
int ret = 0;
|
|
|
|
#if defined(TFA_ENABLE_STC_TUNING)
|
|
if (tfa_class) {
|
|
tfa_stc_dev = device_create(tfa_class,
|
|
NULL, DEV_ID_TFA_STC, NULL, TFA_STC_DEV_NAME);
|
|
if (!IS_ERR(tfa_stc_dev)) {
|
|
ret = sysfs_create_group(&tfa_stc_dev->kobj,
|
|
&tfa_stc_attr_grp);
|
|
if (ret)
|
|
pr_err("%s: failed to create sysfs group. ret (%d)\n",
|
|
__func__, ret);
|
|
}
|
|
}
|
|
#endif /* TFA_ENABLE_STC_TUNING */
|
|
|
|
pr_info("%s: initialized (%d)\n", __func__,
|
|
(tfa_class != NULL) ? 1 : 0);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void tfa98xx_stc_exit(struct class *tfa_class)
|
|
{
|
|
#if defined(TFA_ENABLE_STC_TUNING)
|
|
device_destroy(tfa_class, DEV_ID_TFA_STC);
|
|
#endif
|
|
pr_info("exited\n");
|
|
}
|
|
|