6db4831e98
Android 14
1138 lines
30 KiB
C
1138 lines
30 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
* Author: Michael Hsiao <michael.hsiao@mediatek.com>
|
|
*/
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Filename:
|
|
* ---------
|
|
* mt6583.c
|
|
*
|
|
* Project:
|
|
* --------
|
|
* MT6583 Audio Driver Kernel Function
|
|
*
|
|
* Description:
|
|
* ------------
|
|
* Audio register
|
|
*
|
|
* Author:
|
|
* -------
|
|
* Chipeng Chang
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* C O M P I L E R F L A G S
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* E X T E R N A L R E F E R E N C E S
|
|
*****************************************************************************/
|
|
|
|
#include "mtk-auddrv-afe.h"
|
|
#include "mtk-auddrv-ana.h"
|
|
#include "mtk-auddrv-clk.h"
|
|
#include "mtk-auddrv-common.h"
|
|
#include "mtk-auddrv-def.h"
|
|
#include "mtk-auddrv-kernel.h"
|
|
#include "mtk-soc-afe-control.h"
|
|
#include "mtk-soc-analog-type.h"
|
|
#include "mtk-soc-digital-type.h"
|
|
#include "mtk-soc-pcm-common.h"
|
|
#include "mtk-soc-pcm-platform.h"
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include "mtk-auddrv-common-func.h"
|
|
#include "mtk-auddrv-gpio.h"
|
|
#include "mtk-soc-codec-63xx.h"
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/time.h>
|
|
|
|
#include <linux/fb.h>
|
|
#include <linux/notifier.h>
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
#include <linux/compat.h>
|
|
#endif
|
|
|
|
#include "mtk-soc-speaker-amp.h"
|
|
|
|
/*
|
|
* function implementation
|
|
*/
|
|
|
|
static int mtk_afe_routing_probe(struct platform_device *pdev);
|
|
static int mtk_routing_pcm_close(struct snd_pcm_substream *substream);
|
|
static int mtk_afe_routing_component_probe(struct snd_soc_component *component);
|
|
|
|
static int mDac_Sinegen = 27; /* "OFF" */
|
|
static const char *const DAC_DL_SINEGEN[] = {
|
|
"I0I1", "I2", "I3I4", "I5I6", "I7I8", "I9", "I10I11",
|
|
"I12I13", "I14", "I15I16", "I17I18", "I19I20", "I21I22", "O0O1",
|
|
"O2", "O3O4", "O5O6", "O7O8", "O9O10", "O11", "O12",
|
|
"O13O14", "O15O16", "O17O18", "O19O20", "O21O22", "O23O24", "OFF",
|
|
"O3", "O4", "I25I26", "O25", "O28O29", "I23I24", "O32O33",
|
|
"I27I28", "O30O31", "O34", "O36O37", "O38O39", "I34I35",
|
|
};
|
|
|
|
static int mDac_SampleRate = 8; /* 48kHz */
|
|
static const char *const DAC_DL_SINEGEN_SAMEPLRATE[] = {
|
|
"8K", "11K", "12K", "16K", "22K", "24K", "32K",
|
|
"44K", "48K", "88k", "96k", "176k", "192k"};
|
|
|
|
static int mDac_Sinegen_Amplitude = 6; /* "1/2" */
|
|
static const char *const DAC_DL_SINEGEN_AMPLITUE[] = {
|
|
"1/128", "1/64", "1/32", "1/16", "1/8", "1/4", "1/2", "1"};
|
|
static const char *const spk_type_str[] = {"MTK_SPK_NOT_SMARTPA",
|
|
"MTK_SPK_RICHTEK_RT5509",
|
|
#if defined(CONFIG_SND_SOC_TAS5782M)
|
|
"MTK_SPK_TI_TAS5782M",
|
|
#endif
|
|
"MTK_SPK_MTK_MT6660"};
|
|
|
|
static bool mEnableSideToneFilter;
|
|
static const char *const ENABLESTF[] = {"Off", "On"};
|
|
static int stf_gain;
|
|
static int stf_positive_gain_db;
|
|
|
|
static int mAudio_Mode;
|
|
static const char *const ANDROID_AUDIO_MODE[] = {
|
|
"Normal_Mode", "Ringtone_Mode", "Incall_Mode",
|
|
"Communication_Mode", "Incall2_Mode", "Incall_External_Mode"};
|
|
static const char *const InterModemPcm_ASRC_Switch[] = {"Off", "On"};
|
|
static const char *const Audio_Debug_Setting[] = {"Off", "On"};
|
|
static const char *const Audio_IPOH_State[] = {"Off", "On"};
|
|
static const char *const Audio_I2S1_Setting[] = {"Off", "On"};
|
|
|
|
static bool AudDrvSuspendStatus;
|
|
/* static bool mModemPcm_ASRC_on = false; */
|
|
static bool AudioI2S1Setting;
|
|
|
|
static bool AudDrvSuspend_ipoh_Status;
|
|
static int audio_dpd_switch;
|
|
|
|
int Get_Audio_Mode(void)
|
|
{
|
|
return mAudio_Mode;
|
|
}
|
|
|
|
static int Audio_SineGen_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("Audio_AmpR_Get = %d\n", mDac_Sinegen);
|
|
ucontrol->value.integer.value[0] = mDac_Sinegen;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_SineGen_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int index = 0;
|
|
|
|
pr_debug("%s()\n", __func__);
|
|
if (ucontrol->value.enumerated.item[0] > ARRAY_SIZE(DAC_DL_SINEGEN)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
index = ucontrol->value.integer.value[0];
|
|
switch (index) {
|
|
case 0:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I00,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 1:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I02,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 2:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I03,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 3:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I05,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 4:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I07,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 5:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I09,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 6:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I11,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 7:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I12,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 8:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I14,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 9:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I15,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 10:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I17,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 11:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I19,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 12:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I21,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 13:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O01,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 14:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O02,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 15:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O03,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 16:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O05,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 17:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O07,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 18:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O09,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 19:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O11,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 20:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O12,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 21:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O13,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 22:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O15,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 23:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O17,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 24:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O19,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 25:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O21,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 26:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O23,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 27:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O11,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, false);
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I00,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, false);
|
|
break;
|
|
case 28:
|
|
Afe_Set_Reg(AFE_SGEN_CON0, 0x2E8c28c2,
|
|
0xffffffff); /* o3o4 but mute o4 */
|
|
break;
|
|
case 29:
|
|
Afe_Set_Reg(AFE_SGEN_CON0, 0x2D8c28c2,
|
|
0xffffffff); /* o3o4 but mute o3 */
|
|
break;
|
|
case 30:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I25,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 31:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O25,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 32:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O28,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 33:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I23,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 34:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O32,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 35:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I27,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
case 36:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O30,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 37:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O34,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 38:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O36,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 39:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O38,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
break;
|
|
case 40:
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I34,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
break;
|
|
default:
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O11,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, false);
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I00,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, false);
|
|
break;
|
|
}
|
|
mDac_Sinegen = index;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_SineGen_SampleRate_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
ucontrol->value.integer.value[0] = mDac_SampleRate;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_SineGen_SampleRate_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int index = 0;
|
|
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(DAC_DL_SINEGEN_SAMEPLRATE)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
index = ucontrol->value.integer.value[0];
|
|
|
|
switch (index) {
|
|
case 0:
|
|
SetSineGenSampleRate(8000);
|
|
break;
|
|
case 1:
|
|
SetSineGenSampleRate(11025);
|
|
break;
|
|
case 2:
|
|
SetSineGenSampleRate(12000);
|
|
break;
|
|
case 3:
|
|
SetSineGenSampleRate(16000);
|
|
break;
|
|
case 4:
|
|
SetSineGenSampleRate(22050);
|
|
break;
|
|
case 5:
|
|
SetSineGenSampleRate(24000);
|
|
break;
|
|
case 6:
|
|
SetSineGenSampleRate(32000);
|
|
break;
|
|
case 7:
|
|
SetSineGenSampleRate(44100);
|
|
break;
|
|
case 8:
|
|
SetSineGenSampleRate(48000);
|
|
break;
|
|
case 9:
|
|
SetSineGenSampleRate(88200);
|
|
break;
|
|
case 10:
|
|
SetSineGenSampleRate(96000);
|
|
break;
|
|
case 11:
|
|
SetSineGenSampleRate(176400);
|
|
break;
|
|
case 12:
|
|
SetSineGenSampleRate(192000);
|
|
break;
|
|
default:
|
|
SetSineGenSampleRate(48000);
|
|
break;
|
|
}
|
|
|
|
mDac_SampleRate = index;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_SineGen_Amplitude_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("Audio_AmpR_Get = %d\n", mDac_Sinegen_Amplitude);
|
|
ucontrol->value.integer.value[0] = mDac_Sinegen_Amplitude;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_SineGen_Amplitude_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int index = 0;
|
|
|
|
pr_debug("%s()\n", __func__);
|
|
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(DAC_DL_SINEGEN_AMPLITUE)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
index = ucontrol->value.integer.value[0];
|
|
SetSineGenAmplitude(index);
|
|
mDac_Sinegen_Amplitude = index;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_STF_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("Audio_SideTone_Get = %d\n", mEnableSideToneFilter);
|
|
ucontrol->value.integer.value[0] = mEnableSideToneFilter;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_STF_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int index = 0;
|
|
|
|
if (ucontrol->value.enumerated.item[0] > ARRAY_SIZE(ENABLESTF)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
index = ucontrol->value.integer.value[0];
|
|
if (mEnableSideToneFilter != index) {
|
|
mEnableSideToneFilter = index;
|
|
EnableSideToneFilter(mEnableSideToneFilter);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int stf_gain_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
ucontrol->value.integer.value[0] = stf_gain;
|
|
return 0;
|
|
}
|
|
|
|
static int stf_gain_set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
stf_gain = ucontrol->value.integer.value[0];
|
|
set_stf_gain(stf_gain);
|
|
return 0;
|
|
}
|
|
|
|
static int stf_positive_gain_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
ucontrol->value.integer.value[0] = stf_positive_gain_db;
|
|
return 0;
|
|
}
|
|
|
|
static int stf_positive_gain_set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
stf_positive_gain_db = ucontrol->value.integer.value[0];
|
|
set_stf_positive_gain_db(stf_positive_gain_db);
|
|
return 0;
|
|
}
|
|
|
|
#if 0 /* not used */
|
|
static int Audio_ModemPcm_ASRC_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s(), mModemPcm_ASRC_on=%d\n", __func__, mModemPcm_ASRC_on);
|
|
ucontrol->value.integer.value[0] = mModemPcm_ASRC_on;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int AudioDebug_Setting_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(Audio_Debug_Setting)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O03,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, true);
|
|
msleep(5 * 1000);
|
|
EnableSineGen(Soc_Aud_InterConnectionOutput_O03,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_OUTPUT, false);
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I03,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, true);
|
|
msleep(5 * 1000);
|
|
EnableSineGen(Soc_Aud_InterConnectionInput_I03,
|
|
Soc_Aud_MemIF_Direction_DIRECTION_INPUT, false);
|
|
|
|
Ana_Log_Print();
|
|
Afe_Log_Print();
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void Auddrv_I2S1GpioSet(void)
|
|
{
|
|
|
|
#ifndef CONFIG_FPGA_EARLY_PORTING
|
|
|
|
/* I2S1 gpio set */
|
|
#ifdef CONFIG_OF
|
|
AudDrv_GPIO_I2S_Select(true);
|
|
#else
|
|
mt_set_gpio_mode(GPIO_I2S1_CK_PIN, GPIO_MODE_01);
|
|
mt_set_gpio_mode(GPIO_I2S1_DAT_PIN, GPIO_MODE_01);
|
|
mt_set_gpio_mode(GPIO_I2S1_MCLK_PIN, GPIO_MODE_01);
|
|
mt_set_gpio_mode(GPIO_I2S1_WS_PIN, GPIO_MODE_01);
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
static void Auddrv_I2S1GpioReset(void)
|
|
{
|
|
|
|
#ifndef CONFIG_FPGA_EARLY_PORTING
|
|
|
|
#ifdef CONFIG_OF
|
|
AudDrv_GPIO_I2S_Select(false);
|
|
#else
|
|
mt_set_gpio_mode(GPIO_I2S1_CK_PIN, GPIO_MODE_00);
|
|
mt_set_gpio_mode(GPIO_I2S1_DAT_PIN, GPIO_MODE_00);
|
|
mt_set_gpio_mode(GPIO_I2S1_MCLK_PIN, GPIO_MODE_00);
|
|
mt_set_gpio_mode(GPIO_I2S1_WS_PIN, GPIO_MODE_00);
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
static int AudioDebug_Setting_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s()\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
static int AudioI2S1_Setting_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(Audio_I2S1_Setting)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
AudioI2S1Setting = ucontrol->value.enumerated.item[0];
|
|
if (AudioI2S1Setting == true)
|
|
Auddrv_I2S1GpioSet();
|
|
else
|
|
Auddrv_I2S1GpioReset();
|
|
return 0;
|
|
}
|
|
|
|
static int AudioI2S1_Setting_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s()\n", __func__);
|
|
ucontrol->value.enumerated.item[0] = AudioI2S1Setting;
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
static int Audio_ModemPcm_ASRC_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("+%s()\n", __func__);
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(InterModemPcm_ASRC_Switch)) {
|
|
pr_warn("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
mModemPcm_ASRC_on = (bool) ucontrol->value.integer.value[0];
|
|
Audio_ModemPcm2_ASRC_Set(mModemPcm_ASRC_on);
|
|
pr_debug("-%s(), mModemPcm_ASRC_on=%d\n", __func__, mModemPcm_ASRC_on);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int Audio_Ipoh_Setting_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s()\n", __func__);
|
|
ucontrol->value.integer.value[0] = AudDrvSuspend_ipoh_Status;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_Ipoh_Setting_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
if (ucontrol->value.enumerated.item[0] > ARRAY_SIZE(Audio_IPOH_State)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
AudDrvSuspend_ipoh_Status = ucontrol->value.integer.value[0];
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_Mode_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("Audio_SideTone_Get = %d\n", mAudio_Mode);
|
|
ucontrol->value.integer.value[0] = mAudio_Mode;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_Mode_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(ANDROID_AUDIO_MODE)) {
|
|
pr_err("return -EINVAL\n");
|
|
return -EINVAL;
|
|
}
|
|
mAudio_Mode = ucontrol->value.integer.value[0];
|
|
return 0;
|
|
}
|
|
|
|
static int audio_dpd_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s()\n", __func__);
|
|
ucontrol->value.integer.value[0] = audio_dpd_switch;
|
|
return 0;
|
|
}
|
|
|
|
static int audio_dpd_set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int enable = ucontrol->value.integer.value[0];
|
|
|
|
pr_debug("%s(), enable = %d\n", __func__, enable);
|
|
if (ucontrol->value.enumerated.item[0] >
|
|
ARRAY_SIZE(Audio_Debug_Setting)) {
|
|
pr_err("%s(), return -EINVAL\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (get_afe_platform_ops()->set_dpd_module == NULL) {
|
|
pr_warn("%s(), set_dpd_module not implement\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
get_afe_platform_ops()->set_dpd_module(enable);
|
|
audio_dpd_switch = enable;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef AUDIO_DL2_ISR_COPY_SUPPORT
|
|
|
|
static int Audio_DL2_DataTransfer(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
#ifdef CONFIG_COMPAT
|
|
void *addr = compat_ptr(ucontrol->value.integer.value[0]);
|
|
#else
|
|
void *addr = (void *)ucontrol->value.integer.value[0];
|
|
#endif
|
|
|
|
unsigned int size = ucontrol->value.integer.value[1];
|
|
|
|
|
|
mtk_dl2_copy2buffer(addr, size);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int Audio_LowLatencyDebug_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
ucontrol->value.integer.value[0] = get_LowLatencyDebug();
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_LowLatencyDebug_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
set_LowLatencyDebug(ucontrol->value.integer.value[0]);
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_AssignDRAM_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s()\n", __func__);
|
|
ucontrol->value.integer.value[0] = 0;
|
|
return 0;
|
|
}
|
|
|
|
static int Audio_AssignDRAM_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
unsigned int value = ucontrol->value.integer.value[0];
|
|
|
|
pr_debug("%s(), meminterface %d\n", __func__, value);
|
|
if (value < Soc_Aud_Digital_Block_NUM_OF_MEM_INTERFACE) {
|
|
struct afe_mem_control_t *pMemControl = Get_Mem_ControlT(value);
|
|
|
|
pMemControl->mAssignDRAM = true;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int spk_type_get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
int index = mtk_spk_get_type();
|
|
|
|
pr_debug("speaker_amp_index_get = %d\n", index);
|
|
ucontrol->value.integer.value[0] = index;
|
|
return 0;
|
|
}
|
|
|
|
static const struct soc_enum spk_type_enum[] = {
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_type_str), spk_type_str),
|
|
};
|
|
|
|
static const struct soc_enum Audio_Routing_Enum[] = {
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(DAC_DL_SINEGEN), DAC_DL_SINEGEN),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(DAC_DL_SINEGEN_SAMEPLRATE),
|
|
DAC_DL_SINEGEN_SAMEPLRATE),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(DAC_DL_SINEGEN_AMPLITUE),
|
|
DAC_DL_SINEGEN_AMPLITUE),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ENABLESTF), ENABLESTF),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ANDROID_AUDIO_MODE), ANDROID_AUDIO_MODE),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(InterModemPcm_ASRC_Switch),
|
|
InterModemPcm_ASRC_Switch),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(Audio_Debug_Setting),
|
|
Audio_Debug_Setting),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(Audio_IPOH_State), Audio_IPOH_State),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(Audio_I2S1_Setting), Audio_I2S1_Setting),
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_type_str), spk_type_str),
|
|
};
|
|
|
|
static const struct snd_kcontrol_new Audio_snd_routing_controls[] = {
|
|
SOC_ENUM_EXT("Audio_SineGen_Switch", Audio_Routing_Enum[0],
|
|
Audio_SineGen_Get, Audio_SineGen_Set),
|
|
SOC_ENUM_EXT("Audio_SineGen_SampleRate", Audio_Routing_Enum[1],
|
|
Audio_SineGen_SampleRate_Get,
|
|
Audio_SineGen_SampleRate_Set),
|
|
SOC_ENUM_EXT("Audio_SineGen_Amplitude", Audio_Routing_Enum[2],
|
|
Audio_SineGen_Amplitude_Get, Audio_SineGen_Amplitude_Set),
|
|
SOC_ENUM_EXT("Audio_Sidetone_Switch", Audio_Routing_Enum[3],
|
|
Audio_STF_Get, Audio_STF_Set),
|
|
SOC_SINGLE_EXT("Sidetone_Gain", SND_SOC_NOPM, 0, 0x7fff, 0,
|
|
stf_gain_get, stf_gain_set),
|
|
SOC_SINGLE_EXT("Sidetone_Positive_Gain_dB", SND_SOC_NOPM, 0, 100, 0,
|
|
stf_positive_gain_get, stf_positive_gain_set),
|
|
SOC_ENUM_EXT("Audio_Mode_Switch", Audio_Routing_Enum[4], Audio_Mode_Get,
|
|
Audio_Mode_Set),
|
|
SOC_ENUM_EXT("Audio_Debug_Setting", Audio_Routing_Enum[6],
|
|
AudioDebug_Setting_Get, AudioDebug_Setting_Set),
|
|
SOC_ENUM_EXT("Audio_Ipoh_Setting", Audio_Routing_Enum[7],
|
|
Audio_Ipoh_Setting_Get, Audio_Ipoh_Setting_Set),
|
|
SOC_ENUM_EXT("Audio_I2S1_Setting", Audio_Routing_Enum[8],
|
|
AudioI2S1_Setting_Get, AudioI2S1_Setting_Set),
|
|
#ifdef AUDIO_DL2_ISR_COPY_SUPPORT
|
|
SOC_DOUBLE_EXT("Audio_DL2_DataTransfer", SND_SOC_NOPM, 0, 1, 65536, 0,
|
|
NULL, Audio_DL2_DataTransfer),
|
|
#endif
|
|
SOC_SINGLE_EXT("Audio_LowLatency_Debug", SND_SOC_NOPM, 0, 0x20000, 0,
|
|
Audio_LowLatencyDebug_Get, Audio_LowLatencyDebug_Set),
|
|
SOC_ENUM_EXT("Audio_DPD_Switch", Audio_Routing_Enum[6], audio_dpd_get,
|
|
audio_dpd_set),
|
|
SOC_SINGLE_EXT("Audio_Assign_DRAM", SND_SOC_NOPM, 0, 0x20000, 0,
|
|
Audio_AssignDRAM_Get, Audio_AssignDRAM_Set),
|
|
SOC_ENUM_EXT("MTK_SPK_TYPE_GET",
|
|
Audio_Routing_Enum[9], spk_type_get, NULL),
|
|
};
|
|
|
|
void EnAble_Anc_Path(int state)
|
|
{
|
|
|
|
pr_debug("%s not supported in 6752!!!\n ", __func__);
|
|
}
|
|
|
|
static int m_Anc_State = AUDIO_ANC_ON;
|
|
static int Afe_Anc_Get(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
pr_debug("%s()\n", __func__);
|
|
ucontrol->value.integer.value[0] = m_Anc_State;
|
|
return 0;
|
|
}
|
|
|
|
static int Afe_Anc_Set(struct snd_kcontrol *kcontrol,
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
{
|
|
EnAble_Anc_Path(ucontrol->value.integer.value[0]);
|
|
m_Anc_State = ucontrol->value.integer.value[0];
|
|
return 0;
|
|
}
|
|
|
|
/* here start uplink power function */
|
|
static const char *const Afe_Anc_function[] = {"ANCON", "ANCOFF"};
|
|
|
|
static const struct soc_enum Afe_Anc_Enum[] = {
|
|
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(Afe_Anc_function), Afe_Anc_function),
|
|
};
|
|
|
|
static const struct snd_kcontrol_new Afe_Anc_controls[] = {
|
|
SOC_ENUM_EXT("Pmic_Anc_Switch", Afe_Anc_Enum[0], Afe_Anc_Get,
|
|
Afe_Anc_Set),
|
|
};
|
|
|
|
static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
|
|
.count = ARRAY_SIZE(soc_high_supported_sample_rates),
|
|
.list = soc_high_supported_sample_rates,
|
|
.mask = 0,
|
|
};
|
|
|
|
static int mtk_routing_pcm_open(struct snd_pcm_substream *substream)
|
|
{
|
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
|
int ret = 0;
|
|
|
|
pr_debug("mtk_routing_pcm_open\n");
|
|
|
|
ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
|
|
&constraints_sample_rates);
|
|
|
|
/* print for hw pcm information */
|
|
pr_debug("mtk_routing_pcm_open runtime rate = %d channels = %d\n",
|
|
runtime->rate, runtime->channels);
|
|
if (substream->pcm->device & 1) {
|
|
runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
|
|
runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
|
|
}
|
|
if (substream->pcm->device & 2)
|
|
runtime->hw.info &=
|
|
~(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID);
|
|
|
|
if (ret < 0) {
|
|
pr_debug("mtk_routing_pcm_close\n");
|
|
mtk_routing_pcm_close(substream);
|
|
return ret;
|
|
}
|
|
pr_debug("mtk_routing_pcm_open return\n");
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_routing_pcm_close(struct snd_pcm_substream *substream)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_routing_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
{
|
|
pr_debug("%s cmd = %d\n", __func__, cmd);
|
|
switch (cmd) {
|
|
case SNDRV_PCM_TRIGGER_START:
|
|
case SNDRV_PCM_TRIGGER_RESUME:
|
|
case SNDRV_PCM_TRIGGER_STOP:
|
|
case SNDRV_PCM_TRIGGER_SUSPEND:
|
|
break;
|
|
}
|
|
return -EINVAL;
|
|
}
|
|
|
|
static int mtk_routing_pcm_copy(struct snd_pcm_substream *substream,
|
|
int channel,
|
|
unsigned long pos,
|
|
void __user *buf,
|
|
unsigned long bytes)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_routing_pcm_silence(struct snd_pcm_substream *substream,
|
|
int channel,
|
|
unsigned long pos,
|
|
unsigned long bytes)
|
|
{
|
|
return 0; /* do nothing */
|
|
}
|
|
|
|
static void *dummy_page[2];
|
|
|
|
static struct page *mtk_routing_pcm_page(struct snd_pcm_substream *substream,
|
|
unsigned long offset)
|
|
{
|
|
return virt_to_page(dummy_page[substream->stream]); /* the same page */
|
|
}
|
|
|
|
static int mtk_routing_pcm_prepare(struct snd_pcm_substream *substream)
|
|
{
|
|
pr_debug("mtk_alsa_prepare\n");
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_routing_pcm_hw_params(struct snd_pcm_substream *substream,
|
|
struct snd_pcm_hw_params *hw_params)
|
|
{
|
|
int ret = 0;
|
|
|
|
pr_debug("mtk_routing_pcm_hw_params\n");
|
|
return ret;
|
|
}
|
|
|
|
static int mtk_routing_pcm_hw_free(struct snd_pcm_substream *substream)
|
|
{
|
|
pr_debug("mtk_routing_pcm_hw_free\n");
|
|
return snd_pcm_lib_free_pages(substream);
|
|
}
|
|
|
|
static struct snd_pcm_ops mtk_afe_ops = {
|
|
.open = mtk_routing_pcm_open,
|
|
.close = mtk_routing_pcm_close,
|
|
.ioctl = snd_pcm_lib_ioctl,
|
|
.hw_params = mtk_routing_pcm_hw_params,
|
|
.hw_free = mtk_routing_pcm_hw_free,
|
|
.prepare = mtk_routing_pcm_prepare,
|
|
.trigger = mtk_routing_pcm_trigger,
|
|
.copy_user = mtk_routing_pcm_copy,
|
|
.fill_silence = mtk_routing_pcm_silence,
|
|
.page = mtk_routing_pcm_page,
|
|
};
|
|
|
|
static struct snd_soc_component_driver mtk_soc_routing_component = {
|
|
.name = AFE_PCM_NAME,
|
|
.ops = &mtk_afe_ops,
|
|
.probe = mtk_afe_routing_component_probe,
|
|
};
|
|
|
|
static int mtk_afe_routing_probe(struct platform_device *pdev)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
|
|
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
|
if (!pdev->dev.dma_mask)
|
|
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
|
|
|
|
if (pdev->dev.of_node)
|
|
dev_set_name(&pdev->dev, "%s", MT_SOC_ROUTING_PCM);
|
|
pdev->name = pdev->dev.kobj.name;
|
|
|
|
pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
|
|
return snd_soc_register_component(&pdev->dev,
|
|
&mtk_soc_routing_component,
|
|
NULL,
|
|
0);
|
|
}
|
|
|
|
static int mtk_afe_routing_component_probe(struct snd_soc_component *component)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
|
|
/* add controls */
|
|
snd_soc_add_component_controls(component, Audio_snd_routing_controls,
|
|
ARRAY_SIZE(Audio_snd_routing_controls));
|
|
snd_soc_add_component_controls(component, Afe_Anc_controls,
|
|
ARRAY_SIZE(Afe_Anc_controls));
|
|
/*Auddrv_Devtree_Init();*/
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_afe_routing_remove(struct platform_device *pdev)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
snd_soc_unregister_component(&pdev->dev);
|
|
return 0;
|
|
}
|
|
|
|
/* supend and resume function */
|
|
static int mtk_routing_pm_ops_suspend(struct device *device)
|
|
{
|
|
pr_debug("%s\n", __func__);
|
|
|
|
if (get_voice_status() || get_voice_md2_status() ||
|
|
#ifdef _NON_COMMON_FEATURE_READY
|
|
get_voice_ultra_status() ||
|
|
#endif
|
|
get_voice_usb_status())
|
|
return 0;
|
|
|
|
if (AudDrvSuspendStatus == false) {
|
|
/*BackUp_Audio_Register();*/ /* KC: no use */
|
|
if (ConditionEnterSuspend() == true) {
|
|
SetAnalogSuspend(true);
|
|
/* clkmux_sel(MT_MUX_AUDINTBUS, 0, "AUDIO");
|
|
* select
|
|
* 26M
|
|
*/
|
|
/* AudDrv_Suspend_Clk_Off(); */
|
|
/* Pull high for 6757p LPDDR3 low power */
|
|
handle_suspend(true);
|
|
}
|
|
AudDrvSuspendStatus = true;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_pm_ops_suspend_ipo(struct device *device)
|
|
{
|
|
pr_debug("%s", __func__);
|
|
AudDrvSuspend_ipoh_Status = true;
|
|
return mtk_routing_pm_ops_suspend(device);
|
|
}
|
|
|
|
static int mtk_routing_pm_ops_resume(struct device *device)
|
|
{
|
|
pr_debug("%s\n ", __func__);
|
|
if (AudDrvSuspendStatus == true) {
|
|
/* AudDrv_Suspend_Clk_On(); */
|
|
if (ConditionEnterSuspend() == true) {
|
|
/*Restore_Audio_Register();*/ /* KC: no use */
|
|
SetAnalogSuspend(false);
|
|
/* Pull high for 6757p LPDDR3 low power */
|
|
handle_suspend(false);
|
|
}
|
|
AudDrvSuspendStatus = false;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int mtk_pm_ops_resume_ipo(struct device *device)
|
|
{
|
|
pr_debug("%s", __func__);
|
|
return mtk_routing_pm_ops_resume(device);
|
|
}
|
|
|
|
const struct dev_pm_ops mtk_routing_pm_ops = {
|
|
.suspend = mtk_routing_pm_ops_suspend,
|
|
.resume = mtk_routing_pm_ops_resume,
|
|
.freeze = mtk_pm_ops_suspend_ipo,
|
|
.thaw = mtk_pm_ops_suspend_ipo,
|
|
.poweroff = mtk_pm_ops_suspend_ipo,
|
|
.restore = mtk_pm_ops_resume_ipo,
|
|
.restore_noirq = mtk_pm_ops_resume_ipo,
|
|
};
|
|
|
|
#ifdef CONFIG_OF
|
|
static const struct of_device_id mt_soc_pcm_routing_of_ids[] = {
|
|
{
|
|
.compatible = "mediatek,mt_soc_pcm_routing",
|
|
},
|
|
{} };
|
|
#endif
|
|
|
|
static struct platform_driver mtk_afe_routing_driver = {
|
|
.driver = {
|
|
|
|
.name = MT_SOC_ROUTING_PCM,
|
|
.owner = THIS_MODULE,
|
|
#ifdef CONFIG_OF
|
|
.of_match_table = mt_soc_pcm_routing_of_ids,
|
|
#endif
|
|
#ifdef CONFIG_PM
|
|
.pm = &mtk_routing_pm_ops,
|
|
#endif
|
|
},
|
|
.probe = mtk_afe_routing_probe,
|
|
.remove = mtk_afe_routing_remove,
|
|
};
|
|
|
|
static int soc_fb_notifier_callback(struct notifier_block *self,
|
|
unsigned long event, void *data)
|
|
{
|
|
struct fb_event *evdata = data;
|
|
int blank;
|
|
|
|
if (event != FB_EVENT_BLANK)
|
|
return 0;
|
|
|
|
blank = *(int *)evdata->data;
|
|
switch (blank) {
|
|
case FB_BLANK_UNBLANK:
|
|
set_screen_state(true);
|
|
break;
|
|
case FB_BLANK_POWERDOWN:
|
|
set_screen_state(false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct notifier_block soc_fb_notif = {
|
|
.notifier_call = soc_fb_notifier_callback,
|
|
};
|
|
|
|
#ifndef CONFIG_OF
|
|
static struct platform_device *soc_mtkafe_routing_dev;
|
|
#endif
|
|
|
|
static int __init mtk_soc_routing_platform_init(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
pr_debug("%s\n", __func__);
|
|
#ifndef CONFIG_OF
|
|
soc_mtkafe_routing_dev = platform_device_alloc(MT_SOC_ROUTING_PCM, -1);
|
|
if (!soc_mtkafe_routing_dev)
|
|
return -ENOMEM;
|
|
|
|
ret = platform_device_add(soc_mtkafe_routing_dev);
|
|
if (ret != 0) {
|
|
platform_device_put(soc_mtkafe_routing_dev);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
ret = platform_driver_register(&mtk_afe_routing_driver);
|
|
|
|
ret = fb_register_client(&soc_fb_notif);
|
|
if (ret)
|
|
pr_err("FAILED TO REGISTER FB CLIENT (%d)\n", ret);
|
|
|
|
return ret;
|
|
}
|
|
module_init(mtk_soc_routing_platform_init);
|
|
|
|
static void __exit mtk_soc_routing_platform_exit(void)
|
|
{
|
|
|
|
platform_driver_unregister(&mtk_afe_routing_driver);
|
|
}
|
|
module_exit(mtk_soc_routing_platform_exit);
|
|
|
|
MODULE_DESCRIPTION("afe routing driver");
|
|
MODULE_LICENSE("GPL");
|