dts: Add new dts files for S400 SBR [1/3]

PD#SWPL-4435

Problem:
    adapt Soundbar solution to S400 SBR platform

Solution:
    new dts file axg_s400_v03sbr.dts changed from axg_s400_v03.dts
    add reference remote control mapping in mesonaxg.dtsi
    add tas5782m

Verify:
    S400+D621 A113D

Change-Id: I6feee3993192656eb66b7ee5a9ff6c85d22075e4
Signed-off-by: bing.jiang <bing.jiang@amlogic.com>
Signed-off-by: yujie.wu <yujie.wu@amlogic.com>
This commit is contained in:
bing.jiang
2019-01-23 09:35:18 +08:00
committed by Jianxin Pan
parent 464e4a4071
commit 5702dfa04b
9 changed files with 5554 additions and 0 deletions

View File

@@ -14800,3 +14800,10 @@ F: arch/arm/boot/dts/amlogic/g12b*_a.dts
F: arch/arm/boot/dts/amlogic/mesong12b.dtsi
F: arch/arm64/boot/dts/amlogic/g12b*_a.dts
F: arch/arm64/boot/dts/amlogic/mesong12b.dtsi
AMLOGIC MESONAXG SBR DTS
M: Bing Jiang <Bing.Jiang@amlogic.com>
F: arch/arm64/boot/dts/amlogic/axg_s400_v03sbr.dts
F: arch/arm/boot/dts/amlogic/axg_s400_v03sbr.dts
F: sound/soc/codecs/amlogic/tas5782m.c
F: sound/soc/codecs/amlogic/tas5782m.h

File diff suppressed because it is too large Load Diff

View File

@@ -424,6 +424,7 @@ CONFIG_AMLOGIC_SND_CODEC_PCM2BT=y
CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y
CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y
CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y
CONFIG_AMLOGIC_SND_SOC_TAS5782M=y
CONFIG_AMLOGIC_SND_SOC_TAS5707=y
CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y
CONFIG_AMLOGIC_SND_SOC_PCM186X=y

File diff suppressed because it is too large Load Diff

View File

@@ -417,6 +417,7 @@ CONFIG_AMLOGIC_SND_CODEC_PDM_DUMMY_CODEC=y
CONFIG_AMLOGIC_SND_CODEC_AMLT9015=y
CONFIG_AMLOGIC_SND_CODEC_AMLT9015S=y
CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC=y
CONFIG_AMLOGIC_SND_SOC_TAS5782M=y
CONFIG_AMLOGIC_SND_SOC_TAS5707=y
CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101=y
CONFIG_AMLOGIC_SND_SOC_PCM186X=y

View File

@@ -101,6 +101,18 @@ config AMLOGIC_SND_CODEC_TL1_ACODEC
#Third part codecs
# Amlogic add codecs
config AMLOGIC_SND_SOC_TAS5782M
bool "Texas Instruments TAS5782M amplifier"
depends on AMLOGIC_SND_SOC_CODECS
depends on I2C
default n
help
Enable support for Texas Instruments TAS5782M CODEC.
Select this if your TAS5782M is connected via an I2C bus.
Enable support for Texas Instruments TAS5782M CODEC.
Select this if your TAS5782M is connected via an I2C bus.
config AMLOGIC_SND_SOC_TAS5707
bool "Texas Instruments TAS5707 amplifier"
depends on AMLOGIC_SND_SOC_CODECS

View File

@@ -12,6 +12,7 @@ snd-soc-aml_codec_txlx_acodec-objs := aml_codec_txlx_acodec.o
snd-soc-aml_codec_tl1_acodec-objs := aml_codec_tl1_acodec.o
#Third part codecs
snd-soc-tas5782m-objs := tas5782m.o
snd-soc-tas5707-objs := tas5707.o
snd-soc-tlv320adc3101-objs := tlv320adc3101.o
snd-soc-pcm186x-objs := pcm186x.o pcm186x-i2c.o pcm186x-spi.o
@@ -31,6 +32,7 @@ obj-$(CONFIG_AMLOGIC_SND_CODEC_TXLX_ACODEC) += snd-soc-aml_codec_txlx_acodec.o
obj-$(CONFIG_AMLOGIC_SND_CODEC_TL1_ACODEC) += snd-soc-aml_codec_tl1_acodec.o
#Third part codecs
obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5782M) += snd-soc-tas5782m.o
obj-$(CONFIG_AMLOGIC_SND_SOC_TAS5707) += snd-soc-tas5707.o
obj-$(CONFIG_AMLOGIC_SND_SOC_TLV320ADC3101) += snd-soc-tlv320adc3101.o
obj-$(CONFIG_AMLOGIC_SND_SOC_PCM186X) += snd-soc-pcm186x.o

View File

@@ -0,0 +1,620 @@
/*
* sound/soc/codecs/amlogic/tas5782m.c
*
* Copyright (C) 2019 Amlogic, Inc. 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 as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <sound/tas57xx.h>
#include <linux/amlogic/aml_gpio_consumer.h>
#include "tas5782m.h"
#define DEV_NAME "tas5782m"
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
static void tas5782m_early_suspend(struct early_suspend *h);
static void tas5782m_late_resume(struct early_suspend *h);
#endif
#define tas5782m_RATES (SNDRV_PCM_RATE_8000 | \
SNDRV_PCM_RATE_11025 | \
SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_22050 | \
SNDRV_PCM_RATE_32000 | \
SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
#define tas5782m_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
SNDRV_PCM_FMTBIT_S32_LE)
enum BITSIZE_MODE {
BITSIZE_MODE_16BITS = 0,
BITSIZE_MODE_20BITS = 1,
BITSIZE_MODE_24BITS = 2,
BITSIZE_MODE_32BITS = 3,
};
/* codec private data */
struct tas5782m_priv {
struct i2c_client *i2c;
struct regmap *regmap;
struct snd_soc_codec *codec;
struct tas57xx_platform_data *pdata;
struct work_struct work;
unsigned int work_mode;
unsigned int chip_offset;
/*Platform provided EQ configuration */
int num_eq_conf_texts;
const char **eq_conf_texts;
int eq_cfg;
struct soc_enum eq_conf_enum;
unsigned char Ch1_vol;
unsigned char Ch2_vol;
unsigned char master_vol;
unsigned int mclk;
unsigned int EQ_enum_value;
unsigned int DRC_enum_value;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
};
static int g_sample_bitsize = 32;
static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
static const DECLARE_TLV_DB_SCALE(chvol_tlv, -10300, 50, 1);
static const struct snd_kcontrol_new tas5782m_snd_controls[] = {
};
static int tas5782m_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
return 0;
}
static int tas5782m_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return 0;//-EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_RIGHT_J:
case SND_SOC_DAIFMT_LEFT_J:
break;
default:
return 0;//-EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
case SND_SOC_DAIFMT_NB_IF:
break;
default:
return 0;//-EINVAL;
}
return 0;
}
static int tas5782m_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
unsigned int rate;
rate = params_rate(params);
pr_debug("rate: %u\n", rate);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S24_LE:
case SNDRV_PCM_FORMAT_S24_BE:
pr_debug("24bit\n");
/* fall through */
case SNDRV_PCM_FORMAT_S32_LE:
case SNDRV_PCM_FORMAT_S20_3LE:
case SNDRV_PCM_FORMAT_S20_3BE:
pr_debug("20bit\n");
break;
case SNDRV_PCM_FORMAT_S16_LE:
case SNDRV_PCM_FORMAT_S16_BE:
pr_debug("16bit\n");
break;
default:
return -EINVAL;
}
return 0;
}
static int tas5782m_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
pr_debug("level = %d\n", level);
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
/* Full power on */
break;
case SND_SOC_BIAS_STANDBY:
break;
case SND_SOC_BIAS_OFF:
/* The chip runs through the power down sequence for us. */
break;
}
codec->component.dapm.bias_level = level;
return 0;
}
static const struct snd_soc_dai_ops tas5782m_dai_ops = {
.hw_params = tas5782m_hw_params,
.set_sysclk = tas5782m_set_dai_sysclk,
.set_fmt = tas5782m_set_dai_fmt,
};
static struct snd_soc_dai_driver tas5782m_dai = {
.name = DEV_NAME,
.playback = {
.stream_name = "HIFI Playback",
.channels_min = 2,
.channels_max = 8,
.rates = tas5782m_RATES,
.formats = tas5782m_FORMATS,
},
.ops = &tas5782m_dai_ops,
};
static int reset_tas5782m_GPIO(struct snd_soc_codec *codec)
{
struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec);
struct tas57xx_platform_data *pdata = tas5782m->pdata;
int ret = 0;
if (pdata->reset_pin < 0)
return 0;
ret = devm_gpio_request_one(codec->dev, pdata->reset_pin,
GPIOF_OUT_INIT_LOW, "tas5782m-reset-pin");
if (ret < 0) {
pr_err("failed!!! devm_gpio_request_one = %d!\n", ret);
return -1;
}
gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH);
udelay(1000);
gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW);
udelay(1000);
gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH);
msleep(20);
return 0;
}
static int tas5782m_init_i2s_tdm_mode(struct snd_soc_codec *codec, int bit_size)
{
struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec);
int work_mod = tas5782m->work_mode;
int tdm_aofs = 0;
unsigned char buf[8] = {0};
int write_count = 0;
enum BITSIZE_MODE bit_value = BITSIZE_MODE_32BITS;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count))
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
buf[0] = 0x7f, buf[1] = 0x00;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count))
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
buf[0] = 0x00, buf[1] = 0x00;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count))
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
if (bit_size == 16)
bit_value = BITSIZE_MODE_16BITS;
else if (bit_size == 20)
bit_value = BITSIZE_MODE_20BITS;
else if (bit_size == 24)
bit_value = BITSIZE_MODE_24BITS;
else if (bit_size == 32)
bit_value = BITSIZE_MODE_32BITS;
buf[0] = 0x28, buf[1] = (work_mod << 4) | bit_value;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) {
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
} else {
pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x data:0x%x\n",
__func__, __LINE__, tas5782m->i2c->addr,
tas5782m->chip_offset, buf[0], buf[1]);
}
if (work_mod == WORK_MODE_TDM) {
buf[0] = 0x00, buf[1] = 0x00;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf,
write_count))
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
buf[0] = 0x7f, buf[1] = 0x00;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf,
write_count))
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
buf[0] = 0x00, buf[1] = 0x00;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf,
write_count))
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
tdm_aofs = bit_size * 2 * (tas5782m->chip_offset - 1);
buf[0] = 0x29, buf[1] = tdm_aofs;
write_count = 2;
if (write_count != i2c_master_send(tas5782m->i2c, buf,
write_count)) {
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
} else {
pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x",
__func__, __LINE__, tas5782m->i2c->addr,
tas5782m->chip_offset, buf[0]);
pr_debug("tdm_aofs:0x%x SCLKS\n", tdm_aofs);
}
}
return 0;
}
static void tas5782m_init_func(struct work_struct *p_work)
{
struct tas5782m_priv *tas5782m;
struct snd_soc_codec *codec;
struct i2c_client *i2c;
int i = 0, j = 0, k = 0;
int value_count;
unsigned char buf[64] = {0};
int write_count = 0;
int data_row = 0;
tas5782m = container_of(
p_work, struct tas5782m_priv, work);
codec = tas5782m->codec;
reset_tas5782m_GPIO(codec);
//init register
tas5782m = snd_soc_codec_get_drvdata(codec);
dev_info(codec->dev, "tas5782m_init id=%d\n", tas5782m->chip_offset);
i2c = tas5782m->i2c;
value_count = ARRAY_SIZE(tas5782m_reg_defaults);
for (i = 0; i < value_count;) {
if (tas5782m_reg_defaults[i].reg == CFG_META_BURST) {
if (tas5782m_reg_defaults[i].def == 2) {
data_row = 1;
write_count =
tas5782m_reg_defaults[i].def;
} else {
data_row =
(tas5782m_reg_defaults[i].def
+ 2) >> 1;
write_count =
tas5782m_reg_defaults[i].def
+ 1;
}
i++;
j = 0, k = 0;
for (k = 0; k < data_row; k++) {
buf[j++] =
tas5782m_reg_defaults[i+k].reg;
buf[j++] =
tas5782m_reg_defaults[i+k].def;
}
i += data_row;
//dump_buf(buf, k);
if (write_count !=
i2c_master_send(i2c, buf,
write_count)) {
pr_err("%s %d !!!!! i2c_master_send error !!!!!\n",
__func__, __LINE__);
break;
}
} else {
i++;
pr_info("%s %d warning: register value error!\n",
__func__, __LINE__);
}
}
tas5782m_init_i2s_tdm_mode(codec, g_sample_bitsize);
}
static int tas5782m_probe(struct snd_soc_codec *codec)
{
struct tas5782m_priv *tas5782m;
#ifdef CONFIG_HAS_EARLYSUSPEND
tas5782m->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
tas5782m->early_suspend.suspend = tas5782m_early_suspend;
tas5782m->early_suspend.resume = tas5782m_late_resume;
tas5782m->early_suspend.param = codec;
register_early_suspend(&(tas5782m->early_suspend));
#endif
tas5782m = snd_soc_codec_get_drvdata(codec);
tas5782m->codec = codec;
INIT_WORK(&tas5782m->work, tas5782m_init_func);
schedule_work(&tas5782m->work);
return 0;
}
static int tas5782m_remove(struct snd_soc_codec *codec)
{
struct tas5782m_priv *tas5782m;
#ifdef CONFIG_HAS_EARLYSUSPEND
struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec);
unregister_early_suspend(&(tas5782m->early_suspend));
#endif
tas5782m = snd_soc_codec_get_drvdata(codec);
cancel_work_sync(&tas5782m->work);
return 0;
}
#ifdef CONFIG_PM
static int tas5782m_suspend(struct snd_soc_codec *codec)
{
struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev);
dev_info(codec->dev, "tas5782m_suspend!\n");
if (pdata && pdata->suspend_func)
pdata->suspend_func();
return 0;
}
static int tas5782m_resume(struct snd_soc_codec *codec)
{
struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev);
struct tas5782m_priv *tas5782m;
dev_info(codec->dev, "tas5782m_resume!\n");
if (pdata && pdata->resume_func)
pdata->resume_func();
tas5782m = snd_soc_codec_get_drvdata(codec);
tas5782m->codec = codec;
INIT_WORK(&tas5782m->work, tas5782m_init_func);
schedule_work(&tas5782m->work);
return 0;
}
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
static void tas5782m_early_suspend(struct early_suspend *h)
{
}
static void tas5782m_late_resume(struct early_suspend *h)
{
}
#endif
static const struct snd_soc_dapm_widget tas5782m_dapm_widgets[] = {
SND_SOC_DAPM_DAC("DAC", "HIFI Playback", SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_codec_driver soc_codec_dev_tas5782m = {
.probe = tas5782m_probe,
.remove = tas5782m_remove,
#ifdef CONFIG_PM
.suspend = tas5782m_suspend,
.resume = tas5782m_resume,
#endif
.set_bias_level = tas5782m_set_bias_level,
.component_driver = {
.controls = tas5782m_snd_controls,
.num_controls = ARRAY_SIZE(tas5782m_snd_controls),
.dapm_widgets = tas5782m_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tas5782m_dapm_widgets),
}
};
/*
*static const struct regmap_config tas5782m_regmap = {
* .reg_bits = 8,
* .val_bits = 8,
*
* .max_register = tas5782m_REGISTER_COUNT,
* .reg_defaults = tas5782m_reg_defaults,
* .num_reg_defaults =
* sizeof(tas5782m_reg_defaults)/sizeof(tas5782m_reg_defaults[0]),
* .cache_type = REGCACHE_RBTREE,
*};
*/
static int tas5782m_parse_dts(struct tas5782m_priv *tas5782m,
struct device_node *np)
{
int ret = 0;
int reset_pin = -1;
reset_pin = of_get_named_gpio(np, "reset_pin", 0);
if (reset_pin < 0) {
pr_err("%s fail to get reset pin from dts!\n", __func__);
ret = -1;
} else {
pr_debug("%s pdata->reset_pin = %d!\n", __func__, reset_pin);
}
tas5782m->pdata->reset_pin = reset_pin;
ret = of_property_read_u32(np, "work_mode", &tas5782m->work_mode);
pr_debug("tas5782m->work_mode:%d(%s)!\n", tas5782m->work_mode,
(tas5782m->work_mode == WORK_MODE_I2S)?"i2s":"tdm");
ret = of_property_read_u32(np, "chip_offset", &tas5782m->chip_offset);
pr_debug("tas5782m->chip_offset:%d!\n", tas5782m->chip_offset);
return ret;
}
static int tas5782m_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct tas5782m_priv *tas5782m;
struct tas57xx_platform_data *pdata;
int ret;
const char *codec_name = NULL;
pr_debug("i2c->addr=0x%x\n", i2c->addr);
tas5782m = devm_kzalloc(&i2c->dev,
sizeof(struct tas5782m_priv), GFP_KERNEL);
if (!tas5782m)
return -ENOMEM;
tas5782m->i2c = i2c;
/*
* tas5782m->regmap = devm_regmap_init_i2c(i2c, &tas5782m_regmap);
* if (IS_ERR(tas5782m->regmap)) {
* ret = PTR_ERR(tas5782m->regmap);
* dev_err(&i2c->dev,
* "Failed to allocate register map: %d\n", ret);
* return ret;
* }
*/
pdata = devm_kzalloc(&i2c->dev,
sizeof(struct tas57xx_platform_data), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
tas5782m->pdata = pdata;
tas5782m_parse_dts(tas5782m, i2c->dev.of_node);
if (of_property_read_string(i2c->dev.of_node,
"codec_name", &codec_name)) {
pr_info("no codec name\n");
ret = -1;
}
pr_debug("aux name = %s\n", codec_name);
if (codec_name)
dev_set_name(&i2c->dev, "%s", codec_name);
i2c_set_clientdata(i2c, tas5782m);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_tas5782m, &tas5782m_dai, 1);
if (ret != 0)
dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
return ret;
}
static int tas5782m_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}
static const struct i2c_device_id tas5782m_i2c_id[] = {
{ "tas5782m", 0 },
{}
};
static const struct of_device_id tas5782m_of_id[] = {
{.compatible = "ti, tas5782m",},
{ /* senitel */ }
};
MODULE_DEVICE_TABLE(of, tas5782m_of_id);
static struct i2c_driver tas5782m_i2c_driver = {
.driver = {
.name = DEV_NAME,
.of_match_table = tas5782m_of_id,
.owner = THIS_MODULE,
},
.probe = tas5782m_i2c_probe,
.remove = tas5782m_i2c_remove,
.id_table = tas5782m_i2c_id,
};
module_i2c_driver(tas5782m_i2c_driver);
MODULE_DESCRIPTION("ASoC tas5782m driver");
MODULE_AUTHOR("AML MM team");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff