mirror of
https://github.com/physwizz/a155-U-u1.git
synced 2025-02-15 00:18:03 +00:00
248 lines
6.4 KiB
C
248 lines
6.4 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* aw882xx_spin.c spin_module
|
|
*
|
|
* Copyright (c) 2019 AWINIC Technology CO., LTD
|
|
*
|
|
* Author: Nick Li <liweilei@awinic.com.cn>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/i2c.h>
|
|
#include <sound/core.h>
|
|
#include <sound/soc.h>
|
|
#include <linux/of_gpio.h>
|
|
#include <linux/device.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/of.h>
|
|
#include <linux/timer.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/version.h>
|
|
#include <linux/input.h>
|
|
|
|
#include "aw882xx_log.h"
|
|
#include "aw882xx.h"
|
|
#include "aw882xx_spin.h"
|
|
|
|
static unsigned int g_spin_mode;
|
|
static unsigned int g_spin_value;
|
|
|
|
static DEFINE_MUTEX(g_spin_lock);
|
|
|
|
int aw_dev_set_channal_mode(struct aw_device *aw_dev,
|
|
struct aw_spin_desc spin_desc, uint32_t spin_val)
|
|
{
|
|
int ret;
|
|
struct aw_reg_ch *rx_desc = &spin_desc.rx_desc;
|
|
|
|
ret = aw_dev->ops.aw_i2c_write_bits(aw_dev, rx_desc->reg, rx_desc->mask,
|
|
spin_desc.spin_table[spin_val].rx_val);
|
|
if (ret < 0) {
|
|
aw_dev_err(aw_dev->dev, "set rx failed");
|
|
return ret;
|
|
}
|
|
|
|
aw_dev_dbg(aw_dev->dev, "set channel mode done!");
|
|
return 0;
|
|
}
|
|
|
|
static int aw_reg_write_spin(struct aw_device *aw_dev,
|
|
uint32_t spin_val, bool mixer_en)
|
|
{
|
|
int ret;
|
|
struct aw_device *local_dev = NULL;
|
|
struct list_head *pos = NULL;
|
|
struct list_head *dev_list = NULL;
|
|
|
|
ret = aw882xx_dev_get_list_head(&dev_list);
|
|
if (ret) {
|
|
aw_dev_err(aw_dev->dev, "get dev list failed");
|
|
return ret;
|
|
}
|
|
|
|
if ((g_spin_mode == AW_REG_MIXER_SPIN_MODE) && (mixer_en)) {
|
|
list_for_each(pos, dev_list) {
|
|
local_dev = container_of(pos, struct aw_device, list_node);
|
|
ret = aw882xx_dsp_set_mixer_en(local_dev, AW_AUDIO_MIX_ENABLE);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
usleep_range(AW_100000_US, AW_100000_US + 10);
|
|
|
|
list_for_each(pos, dev_list) {
|
|
local_dev = container_of(pos, struct aw_device, list_node);
|
|
ret = aw_dev_set_channal_mode(local_dev, local_dev->spin_desc, spin_val);
|
|
if (ret < 0) {
|
|
aw_dev_err(local_dev->dev, "set channal mode failed");
|
|
return ret;
|
|
}
|
|
|
|
if ((g_spin_mode == AW_REG_MIXER_SPIN_MODE) && (mixer_en)) {
|
|
ret = aw882xx_dsp_set_mixer_en(aw_dev, AW_AUDIO_MIX_DSIABLE);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int aw882xx_spin_set_record_val(struct aw_device *aw_dev)
|
|
{
|
|
int ret = -1;
|
|
|
|
mutex_lock(&g_spin_lock);
|
|
if (g_spin_mode == AW_ADSP_SPIN_MODE) {
|
|
ret = aw882xx_dsp_write_spin(g_spin_value);
|
|
if (ret) {
|
|
mutex_unlock(&g_spin_lock);
|
|
return ret;
|
|
}
|
|
} else if ((g_spin_mode == AW_REG_SPIN_MODE) ||
|
|
(g_spin_mode == AW_REG_MIXER_SPIN_MODE)) {
|
|
ret = aw_dev_set_channal_mode(aw_dev, aw_dev->spin_desc, g_spin_value);
|
|
if (ret) {
|
|
mutex_unlock(&g_spin_lock);
|
|
return ret;
|
|
}
|
|
} else {
|
|
aw_dev_info(aw_dev->dev, "do nothing");
|
|
}
|
|
mutex_unlock(&g_spin_lock);
|
|
|
|
aw_dev_info(aw_dev->dev, "set record spin val done");
|
|
return 0;
|
|
}
|
|
|
|
int aw882xx_spin_value_get(struct aw_device *aw_dev,
|
|
uint32_t *spin_val, bool pstream)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (((g_spin_mode == AW_REG_SPIN_MODE) ||
|
|
(g_spin_mode == AW_REG_MIXER_SPIN_MODE)) || (!pstream))
|
|
*spin_val = g_spin_value;
|
|
else if (g_spin_mode == AW_ADSP_SPIN_MODE)
|
|
ret = aw882xx_dsp_read_spin(spin_val);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int aw882xx_spin_value_set(struct aw_device *aw_dev, uint32_t spin_val, bool pstream)
|
|
{
|
|
int ret = 0;
|
|
|
|
mutex_lock(&g_spin_lock);
|
|
if (pstream) {
|
|
if ((g_spin_mode == AW_REG_SPIN_MODE) ||
|
|
(g_spin_mode == AW_REG_MIXER_SPIN_MODE))
|
|
ret = aw_reg_write_spin(aw_dev, spin_val, true);
|
|
else if (g_spin_mode == AW_ADSP_SPIN_MODE)
|
|
ret = aw882xx_dsp_write_spin(spin_val);
|
|
else
|
|
aw_dev_info(aw_dev->dev, "can't set spin value");
|
|
} else {
|
|
if ((g_spin_mode == AW_REG_SPIN_MODE) ||
|
|
(g_spin_mode == AW_REG_MIXER_SPIN_MODE))
|
|
ret = aw_reg_write_spin(aw_dev, spin_val, false);
|
|
else
|
|
aw_dev_info(aw_dev->dev, "stream no start only record spin angle");
|
|
}
|
|
g_spin_value = spin_val;
|
|
mutex_unlock(&g_spin_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int aw_parse_spin_table_dt(struct aw_device *aw_dev)
|
|
{
|
|
int ret = -1;
|
|
const char *str_data = NULL;
|
|
char spin_table_str[AW_SPIN_MAX] = { 0 };
|
|
struct aw_spin_desc *spin_desc = &aw_dev->spin_desc;
|
|
int i;
|
|
|
|
ret = of_property_read_string(aw_dev->dev->of_node, "spin-data", &str_data);
|
|
if (ret < 0) {
|
|
aw_dev_err(aw_dev->dev, "get spin_data failed, close spin function");
|
|
return ret;
|
|
}
|
|
|
|
ret = sscanf(str_data, "%c %c %c %c",
|
|
&spin_table_str[AW_SPIN_0], &spin_table_str[AW_SPIN_90],
|
|
&spin_table_str[AW_SPIN_180], &spin_table_str[AW_SPIN_270]);
|
|
if (ret != AW_SPIN_MAX) {
|
|
aw_dev_err(aw_dev->dev, "unsupported str:%s, close spin function", str_data);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < AW_SPIN_MAX; i++) {
|
|
if (spin_table_str[i] == 'l' || spin_table_str[i] == 'L') {
|
|
spin_desc->spin_table[i].rx_val = spin_desc->rx_desc.left_val;
|
|
} else if (spin_table_str[i] == 'r' || spin_table_str[i] == 'R') {
|
|
spin_desc->spin_table[i].rx_val = spin_desc->rx_desc.right_val;
|
|
} else {
|
|
aw_dev_err(aw_dev->dev, "unsupported str:%s, close spin function", str_data);
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int aw_parse_spin_dts(struct aw_device *aw_dev)
|
|
{
|
|
int ret = -1;
|
|
const char *spin_str = NULL;
|
|
|
|
ret = of_property_read_string(aw_dev->dev->of_node, "spin-mode", &spin_str);
|
|
if (ret < 0) {
|
|
g_spin_mode = AW_SPIN_OFF_MODE;
|
|
aw_dev_info(aw_dev->dev, "spin-mode get failed, spin switch off, spin_mode:%d", g_spin_mode);
|
|
return 0;
|
|
}
|
|
|
|
if (!strcmp(spin_str, "dsp_spin"))
|
|
g_spin_mode = AW_ADSP_SPIN_MODE;
|
|
else if (!strcmp(spin_str, "reg_spin"))
|
|
g_spin_mode = AW_REG_SPIN_MODE;
|
|
else if (!strcmp(spin_str, "reg_mixer_spin"))
|
|
g_spin_mode = AW_REG_MIXER_SPIN_MODE;
|
|
else
|
|
g_spin_mode = AW_SPIN_OFF_MODE;
|
|
|
|
if ((g_spin_mode == AW_REG_SPIN_MODE) ||
|
|
(g_spin_mode == AW_REG_MIXER_SPIN_MODE)) {
|
|
ret = aw_parse_spin_table_dt(aw_dev);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
|
|
aw_dev_info(aw_dev->dev, "spin mode is %d", g_spin_mode);
|
|
return 0;
|
|
}
|
|
|
|
int aw882xx_spin_init(struct aw_spin_desc *spin_desc)
|
|
{
|
|
int ret = 0;
|
|
struct aw_device *aw_dev =
|
|
container_of(spin_desc, struct aw_device, spin_desc);
|
|
|
|
ret = aw_parse_spin_dts(aw_dev);
|
|
|
|
if (g_spin_mode == AW_SPIN_OFF_MODE)
|
|
spin_desc->aw_spin_kcontrol_st = AW_SPIN_KCONTROL_DISABLE;
|
|
else
|
|
spin_desc->aw_spin_kcontrol_st = AW_SPIN_KCONTROL_ENABLE;
|
|
|
|
aw_dev_info(aw_dev->dev, "aw_spin_kcontrol_st:%d", spin_desc->aw_spin_kcontrol_st);
|
|
|
|
return ret;
|
|
}
|