unplugged-kernel/sound/soc/mediatek/mt6768/mt6768-mt6358-ref.c

356 lines
11 KiB
C

// SPDX-License-Identifier: GPL-2.0
//
// mt6768-mt6358-ref.c -- mt6768 mt6358 ref dev speaker
//
// Copyright (c) 2022 MediaTek Inc.
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "mt6768-afe-common.h"
#include "mt6768-afe-clk.h"
#include "mt6768-afe-gpio.h"
#include "../../codecs/mt6358.h"
#include "../common/mtk-sp-spk-amp.h"
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include "mt6768-mt6358-ref.h"
int g_pa_type = 0;
int g_fm_pa_mode = 0;
#if defined(CONFIG_SND_SOC_FS1599)
extern fsm_speaker_onn(void);
extern fsm_speaker_off(void);
extern fsm_add_card_controls(struct snd_soc_card *card);
#endif
static bool ref_is_loopback;
struct ext_amp_data {
int gpio_no;
int g_dualspeaker_gpio_no;
int normal_mode;
int speech_mode;
int receiver_mode;
int pa_type_gpio;
int is_fs1599_pa;
int fm_mode;
};
struct ext_amp_data g_spk_amp_data = {
.gpio_no = -1,
.g_dualspeaker_gpio_no = -1,
.normal_mode = -1,
.speech_mode = -1,
.receiver_mode = -1,
.pa_type_gpio = -1,
.is_fs1599_pa = -1,
.fm_mode = -1,
};
#define SPK_WARM_UP_TIME (40)/* unit is ms */
#define NORMAL_MODE 0
#define SPEECH_MODE 1
#define RECEIVER_MODE 2
#define FM_MODE 3
#define GAP (2) /* unit: us */
#define FS_GAP_STA (300) /* unit: us */
#define FS_GAP_HL (10) /* unit: us */
static void ref_ext_amp_sel(bool enable, int mode)
{
if (g_spk_amp_data.gpio_no >= 0 && g_spk_amp_data.normal_mode >= 0 && g_spk_amp_data.speech_mode >= 0){
if(!ref_is_loopback){
if (mode == FM_MODE) {
ref_AudDrv_GPIO_Single_Speaker_Sel(enable, NORMAL_MODE);
}
else {
ref_AudDrv_GPIO_Single_Speaker_Sel(enable, mode);
}
}
if (g_spk_amp_data.g_dualspeaker_gpio_no >= 0){
ref_AudDrv_GPIO_Dual_Speaker_Sel(enable, mode);
}
}
}
void ref_ext_amp_switch(bool enable)
{
extern bool mtk_get_speech_status(void);
if (enable) {
pr_debug("ref_ext_amp_switch+++ ON\n");
if (g_spk_amp_data.is_fs1599_pa > 0) {
#if defined(CONFIG_SND_SOC_FS1599)
fsm_speaker_onn();
#endif
} else {
if(mtk_get_speech_status()){
ref_ext_amp_sel(true, SPEECH_MODE);
} else if (g_fm_pa_mode == 1) {
ref_ext_amp_sel(true, FM_MODE);
g_fm_pa_mode = 0;
} else {
ref_ext_amp_sel(true, NORMAL_MODE);
}
msleep(SPK_WARM_UP_TIME);
}
} else {
pr_debug("ref_ext_amp_switch+++ OFF\n");
if (g_spk_amp_data.is_fs1599_pa > 0) {
#if defined(CONFIG_SND_SOC_FS1599)
fsm_speaker_off();
#endif
} else {
ref_ext_amp_sel(false, 0);
udelay(500);
}
}
}
void ref_parse_dts_node(void)
{
struct device_node *np = of_find_compatible_node(NULL, NULL, "ref_audio,audio");
g_spk_amp_data.gpio_no = -1;
g_spk_amp_data.speech_mode = -1;
g_spk_amp_data.normal_mode = -1;
g_spk_amp_data.receiver_mode = -1;
g_spk_amp_data.pa_type_gpio = -1;
g_spk_amp_data.is_fs1599_pa = -1;
if (np){
if (of_property_read_u32(np, "extamp_fm_mode", &g_spk_amp_data.fm_mode)) {
pr_err("Cannot find extamp_fm_mode!");
}
g_spk_amp_data.g_dualspeaker_gpio_no = of_get_named_gpio(np, "dual_speaker_gpio", 0);
g_spk_amp_data.pa_type_gpio = of_get_named_gpio(np, "amp_type_gpio", 0);
if(g_spk_amp_data.pa_type_gpio >= 0){
if(gpio_get_value(g_spk_amp_data.pa_type_gpio) == 0){
pr_debug("ref_parse_dts_node() use fs pa\n");
g_pa_type = 1;
g_spk_amp_data.gpio_no = of_get_named_gpio(np, "fs_extamp_gpio", 0);
}else{
pr_debug("ref_parse_dts_node() use aw pa\n");
g_pa_type = 0;
g_spk_amp_data.gpio_no = of_get_named_gpio(np, "extamp_gpio", 0);
}
} else {
g_spk_amp_data.gpio_no = of_get_named_gpio(np, "extamp_gpio", 0);
if(g_spk_amp_data.gpio_no >= 0){
pr_debug("ref_parse_dts_node() use aw pa\n");
g_pa_type = 0;
} else {
pr_debug("ref_parse_dts_node() use fs pa\n");
g_spk_amp_data.gpio_no = of_get_named_gpio(np, "fs_extamp_gpio", 0);
if(g_spk_amp_data.gpio_no >= 0){
g_pa_type = 1;
} else {
if (of_property_read_u32(np, "fs1599_pa", &g_spk_amp_data.is_fs1599_pa)) {
pr_err("Cannot find fs1599_pa!\n");
}
}
}
}
if(g_pa_type == 1){
if (of_property_read_u32(np, "fs_extamp_mode", &g_spk_amp_data.normal_mode)) {
pr_err("Cannot find fs_extamp_mode!\n");
}
if (of_property_read_u32(np, "fs_extamp_speech_mode", &g_spk_amp_data.speech_mode)) {
pr_err("Cannot find fs_extamp_speech_mode!\n");
}
if (of_property_read_u32(np, "fs_receiver_mode", &g_spk_amp_data.receiver_mode)) {
pr_err("Cannot find fs_receiver_mode!\n");
}
} else {
if (of_property_read_u32(np, "extamp_mode", &g_spk_amp_data.normal_mode)) {
pr_err("Cannot find extamp_mode!\n");
}
if (of_property_read_u32(np, "extamp_speech_mode", &g_spk_amp_data.speech_mode)) {
pr_err("Cannot find extamp_speech_mode!\n");
}
if (of_property_read_u32(np, "receiver_mode", &g_spk_amp_data.receiver_mode)) {
pr_err("Cannot find receiver_mode!\n");
}
}
pr_debug("ref_parse_dts_node gpio = %d dualspeaker_gpio %d speech_mode = %d, normal_mode = %d\n",
g_spk_amp_data.gpio_no, g_spk_amp_data.g_dualspeaker_gpio_no, g_spk_amp_data.speech_mode, g_spk_amp_data.normal_mode);
}
}
#define RECEIVER_WARM_UP_TIME (40) /* unit is ms */
static int ref_AudDrv_GPIO_Amp_Sel_GetMode(int mode)
{
int ref_amp_mode = 0;
switch (mode) {
case NORMAL_MODE:
ref_amp_mode = g_spk_amp_data.normal_mode;
break;
case SPEECH_MODE:
ref_amp_mode = g_spk_amp_data.speech_mode;
break;
case RECEIVER_MODE:
ref_amp_mode = g_spk_amp_data.receiver_mode;
break;
case FM_MODE:
ref_amp_mode = g_spk_amp_data.fm_mode;
break;
}
return ref_amp_mode;
}
static void ref_AudDrv_GPIO_Single_Speaker_TLTH_delay(void)
{
if(g_pa_type == 1){
udelay(FS_GAP_HL);
} else {
udelay(GAP);
}
}
void ref_AudDrv_GPIO_Single_Speaker_Sel(bool enable, int mode)
{
int i,j;
j = ref_AudDrv_GPIO_Amp_Sel_GetMode(mode);
if (enable) {
if(g_pa_type == 1){
gpio_set_value(g_spk_amp_data.gpio_no, 1);
udelay(FS_GAP_STA);
}
for (i = 0; i < j; i++) {
gpio_set_value(g_spk_amp_data.gpio_no, 0);
ref_AudDrv_GPIO_Single_Speaker_TLTH_delay();
gpio_set_value(g_spk_amp_data.gpio_no, 1);
ref_AudDrv_GPIO_Single_Speaker_TLTH_delay();
}
} else {
gpio_set_value(g_spk_amp_data.gpio_no, 0);
}
}
void ref_AudDrv_GPIO_Dual_Speaker_Sel(bool enable, int mode)
{
int i,j;
j = ref_AudDrv_GPIO_Amp_Sel_GetMode(mode);
if (enable) {
for (i = 0; i < j; i++) {
gpio_set_value(g_spk_amp_data.g_dualspeaker_gpio_no, 0);
udelay(GAP);
gpio_set_value(g_spk_amp_data.g_dualspeaker_gpio_no, 1);
udelay(GAP);
}
} else {
gpio_set_value(g_spk_amp_data.g_dualspeaker_gpio_no, 0);
}
}
static void ref_2N1_Speaker_Change(bool enable)
{
if (enable) {
pr_debug("ref_2N1_Speaker_Change+++ ON\n");
if(ref_is_loopback){
ref_AudDrv_GPIO_Single_Speaker_Sel(true, NORMAL_MODE);
} else {
ref_AudDrv_GPIO_Single_Speaker_Sel(true, RECEIVER_MODE);
}
msleep(RECEIVER_WARM_UP_TIME);
} else {
pr_debug("ref_2N1_Speaker_Change+++ OFF\n");
ref_AudDrv_GPIO_Single_Speaker_Sel(false, RECEIVER_MODE);
udelay(500);
}
}
int ref_2N1_Speaker_Get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("ref_2N1_Speaker_Get \n");
return 0;
}
int ref_2N1_Speaker_Set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
if (ucontrol->value.integer.value[0]) {
ref_2N1_Speaker_Change(true);
} else {
ref_2N1_Speaker_Change(false);
}
return 0;
}
int ref_MidTest_AudDrv_GPIO_Speaker_Get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("ref_MidTest_AudDrv_GPIO_Speaker_Get \n");
return 0;
}
int ref_MidTest_AudDrv_GPIO_Speaker_Set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
if (ucontrol->value.integer.value[0]) {
pr_debug("ref_MidTest_AudDrv_GPIO_Speaker_Sel+++ ON\n");
if (gpio_get_value(g_spk_amp_data.gpio_no)) {
ref_AudDrv_GPIO_Single_Speaker_Sel(false, NORMAL_MODE);
}
ref_is_loopback = true;
mdelay(RECEIVER_WARM_UP_TIME);
} else {
pr_debug("ref_MidTest_AudDrv_GPIO_Speaker_Sel+++ OFF\n");
if (!gpio_get_value(g_spk_amp_data.gpio_no)) {
ref_AudDrv_GPIO_Single_Speaker_Sel(true, NORMAL_MODE);
}
ref_is_loopback = false;
mdelay(RECEIVER_WARM_UP_TIME);
}
return 0;
}
int ref_LoopBack_Get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("%s()\n", __func__);
return 0;
}
int ref_LoopBack_Set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
if (ucontrol->value.integer.value[0]) {
ref_is_loopback = true;
pr_debug("%s(), loopback true!\n", __func__);
} else {
ref_is_loopback = false;
pr_debug("%s(), loopback false!\n", __func__);
}
return 0;
}
int ref_Amp_FM_PA_MODE_Get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("%s()\n", __func__);
return 0;
}
int ref_Amp_FM_PA_MODE_Set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("%s() fm pa type = %d\n", __func__, g_fm_pa_mode);
g_fm_pa_mode = ucontrol->value.integer.value[0];
return 0;
}
int ref_Amp_PA_Type_Get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("%s() amp pa type = %d\n", __func__, g_pa_type);
ucontrol->value.integer.value[0] = g_pa_type;
return 0;
}
int ref_Amp_PA_Type_Set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
pr_debug("%s()\n", __func__);
return 0;
}