audio: auge: fix PAO for frhdmirx [1/2]

PD#SWPL-4010

Problem:
Not detect audio type by PAO for frhdmirx

Solution:
Add hw detect for frdhmirx PAO
audio type is checked by hw for PCM too

Verify:
x301

Change-Id: Ib60d738c69f336866250a8181609503912bf0485
Signed-off-by: Xing Wang <xing.wang@amlogic.com>
This commit is contained in:
Xing Wang
2019-02-27 14:12:11 +08:00
committed by Luke Go
parent 1745b54633
commit 97ee458dc1
5 changed files with 173 additions and 38 deletions

View File

@@ -42,6 +42,15 @@
#define DRV_NAME "EXTN"
#define MAX_INT 0x7ffffff
struct extn_chipinfo {
/* try to check papb before fetch pcpd
* no nonpcm2pcm irq for tl1
*/
bool no_nonpcm2pcm_clr;
};
struct extn {
struct aml_audio_controller *actrl;
struct device *dev;
@@ -69,9 +78,19 @@ struct extn {
int arc_src;
int arc_en;
/* check whether irq generating
* if not, reset
* 'cuase no irq from nonpcm2pcm, do it by sw.
*/
unsigned int frhdmirx_cnt; /* irq counter */
unsigned int frhdmirx_last_cnt;
unsigned int frhdmirx_same_cnt;
bool nonpcm_flag;
struct extn_chipinfo *chipinfo;
};
#define PREALLOC_BUFFER (128 * 1024)
#define PREALLOC_BUFFER (256 * 1024)
#define PREALLOC_BUFFER_MAX (256 * 1024)
#define EXTN_RATES (SNDRV_PCM_RATE_8000_192000)
@@ -100,21 +119,58 @@ static const struct snd_pcm_hardware extn_hardware = {
.channels_max = 32,
};
static void frhdmirx_nonpcm2pcm_clr_reset(struct extn *p_extn)
{
p_extn->frhdmirx_cnt = 0;
p_extn->frhdmirx_last_cnt = 0;
p_extn->frhdmirx_same_cnt = 0;
}
static irqreturn_t extn_ddr_isr(int irq, void *devid)
{
struct snd_pcm_substream *substream =
(struct snd_pcm_substream *)devid;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct device *dev = rtd->platform->dev;
struct extn *p_extn = (struct extn *)dev_get_drvdata(dev);
if (!snd_pcm_running(substream))
return IRQ_HANDLED;
snd_pcm_period_elapsed(substream);
/* check pcm or nonpcm */
if (p_extn &&
p_extn->chipinfo &&
p_extn->chipinfo->no_nonpcm2pcm_clr) {
if (p_extn->frhdmirx_last_cnt == p_extn->frhdmirx_cnt) {
p_extn->frhdmirx_same_cnt++;
if (p_extn->frhdmirx_same_cnt > 5)
frhdmirx_nonpcm2pcm_clr_reset(p_extn);
if (p_extn->frhdmirx_cnt == 0)
p_extn->nonpcm_flag = false;
} else {
p_extn->frhdmirx_last_cnt = p_extn->frhdmirx_cnt;
p_extn->frhdmirx_same_cnt = 0;
p_extn->nonpcm_flag = true;
frhdmirx_clr_PAO_irq_bits();
}
}
return IRQ_HANDLED;
}
static irqreturn_t frhdmirx_isr(int irq, void *devid)
{
struct extn *p_extn = (struct extn *)devid;
p_extn->frhdmirx_cnt++;
if (p_extn->frhdmirx_cnt > MAX_INT - 2)
frhdmirx_nonpcm2pcm_clr_reset(p_extn);
return IRQ_HANDLED;
}
@@ -177,8 +233,12 @@ static int extn_close(struct snd_pcm_substream *substream)
else {
aml_audio_unregister_toddr(p_extn->dev, substream);
if (toddr_src_get() == FRHDMIRX)
if (toddr_src_get() == FRHDMIRX) {
frhdmirx_nonpcm2pcm_clr_reset(p_extn);
if (p_extn->hdmirx_mode == 1)
frhdmirx_clr_PAO_irq_bits();
free_irq(p_extn->irq_frhdmirx, p_extn);
}
}
runtime->private_data = NULL;
@@ -639,7 +699,7 @@ static const struct sppdif_audio_info type_texts[] = {
{3, 0xb, "DTS-I"},
{3, 0x0c, "DTS-II"},
{3, 0x0d, "DTS-III"},
{3, 0x11, "DTS-IV"},
{4, 0x11, "DTS-IV"},
{4, 0, "DTS-HD"},
{5, 0x16, "TRUEHD"},
{6, 0x103, "PAUSE"},
@@ -651,13 +711,16 @@ static const struct soc_enum hdmirx_audio_type_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(spdif_audio_type_texts),
spdif_audio_type_texts);
static int hdmiin_check_audio_type(void)
static int hdmiin_check_audio_type(struct extn *p_extn)
{
int total_num = sizeof(type_texts)/sizeof(struct sppdif_audio_info);
int pc = frhdmirx_get_chan_status_pc();
int audio_type = 0;
int i;
if (!p_extn->nonpcm_flag)
return audio_type;
for (i = 0; i < total_num; i++) {
if (pc == type_texts[i].pc) {
audio_type = type_texts[i].aud_type;
@@ -674,8 +737,12 @@ static int hdmirx_audio_type_get_enum(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
struct extn *p_extn = dev_get_drvdata(component->dev);
ucontrol->value.enumerated.item[0] =
hdmiin_check_audio_type();
hdmiin_check_audio_type(p_extn);
return 0;
}
#endif
@@ -730,6 +797,7 @@ static const struct snd_kcontrol_new extn_controls[] = {
0,
aml_get_atmos_audio_edid,
aml_set_atmos_audio_edid),
SOC_ENUM_EXT("HDMIIN Audio Type",
hdmirx_audio_type_enum,
hdmirx_audio_type_get_enum,
@@ -744,9 +812,18 @@ static const struct snd_soc_component_driver extn_component = {
.name = DRV_NAME,
};
struct extn_chipinfo tl1_extn_chipinfo = {
.no_nonpcm2pcm_clr = true,
};
static const struct of_device_id extn_device_id[] = {
{
.compatible = "amlogic, snd-extn",
.data = &tl1_extn_chipinfo,
},
{
.compatible = "amlogic, tl1-snd-extn",
.data = &tl1_extn_chipinfo,
},
{},
};
@@ -761,9 +838,9 @@ static int extn_platform_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct aml_audio_controller *actrl = NULL;
struct extn *p_extn = NULL;
struct extn_chipinfo *p_chipinfo;
int ret = 0;
p_extn = devm_kzalloc(dev, sizeof(struct extn), GFP_KERNEL);
if (!p_extn)
return -ENOMEM;
@@ -771,6 +848,14 @@ static int extn_platform_probe(struct platform_device *pdev)
p_extn->dev = dev;
dev_set_drvdata(dev, p_extn);
/* match data */
p_chipinfo = (struct extn_chipinfo *)
of_device_get_match_data(dev);
if (!p_chipinfo)
dev_warn_once(dev, "check whether to update chipinfo\n");
else
p_extn->chipinfo = p_chipinfo;
/* get audio controller */
node_prt = of_get_parent(node);
if (node_prt == NULL)
@@ -793,8 +878,8 @@ static int extn_platform_probe(struct platform_device *pdev)
/* Default ARC SRC */
p_extn->arc_src = 1;
/* Default: SPDIF in mode */
p_extn->hdmirx_mode = 0;
/* Default: PAO mode */
p_extn->hdmirx_mode = 1;
ret = snd_soc_register_component(&pdev->dev,
&extn_component,

View File

@@ -15,6 +15,7 @@
*
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include "frhdmirx_hw.h"
#include "regs.h"
@@ -48,7 +49,7 @@ void frhdmirx_src_select(int src)
(bool)src << 23);
}
void frhdmirx_enable_irq_bits(int channels, int src)
static void frhdmirx_enable_irq_bits(int channels, int src)
{
int lane, int_bits = 0, i;
@@ -59,10 +60,11 @@ void frhdmirx_enable_irq_bits(int channels, int src)
/* interrupt bits */
if (src) { /* PAO mode */
int_bits = (0x1 << 24 | /* PAO data: find papb */
0x1 << 16 /* PAO data: find pcpd changed */
int_bits = (
0x1 << INT_PAO_PAPB_MASK | /* find papb */
0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */
);
} else { /* SPDIF Lane*/
} else { /* SPDIF Lane */
int lane_irq_bits = (0x1 << 7 | /* lane: find papb */
0x1 << 6 | /* lane: find papb */
0x1 << 5 | /* lane: find nonpcm to pcm */
@@ -77,6 +79,39 @@ void frhdmirx_enable_irq_bits(int channels, int src)
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL2, int_bits);
}
void frhdmirx_clr_irq_bits(int channels, int src)
{
int lane, int_clr_mask = 0, i;
if (channels % 2)
lane = channels / 2 + 1;
else
lane = channels / 2;
/* interrupt bits */
if (src) { /* PAO mode */
int_clr_mask = (
0x1 << INT_PAO_PAPB_MASK | /* find papb */
0x1 << INT_PAO_PCPD_MASK /* find pcpd changed */
);
} else { /* SPDIF Lane */
int lane_irq_bits = (0x1 << 7 | /* lane: find papb */
0x1 << 6 | /* lane: find valid changed; */
0x1 << 5 | /* lane: find nonpcm to pcm */
0x1 << 4 | /* lane: find pcpd changed */
0x1 << 3 | /* lane: find ch status changed */
0x1 << 1 /* lane: find parity error */
);
for (i = 0; i < lane; i++)
int_clr_mask |= (lane_irq_bits << i);
}
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, ~int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, ~int_clr_mask);
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, int_clr_mask);
}
void frhdmirx_ctrl(int channels, int src)
{
int lane, lane_mask = 0, i;
@@ -84,30 +119,27 @@ void frhdmirx_ctrl(int channels, int src)
/* PAO mode */
if (src) {
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0,
0x1 << 23 | /* slect pao mode */
0x1 << 22 | /* capture input by fall edge*/
0x1 << 7 | /* start sending ch num info out */
0x1 << 8 | /* start detect PAPB */
0x1 << 6 /* chan status sel: pao pc/pd value */);
return;
0x4 << 4 /* chan status sel: pao pc/pd value */
);
} else {
if (channels % 2)
lane = channels / 2 + 1;
else
lane = channels / 2;
for (i = 0; i < lane; i++)
lane_mask |= (1 << i);
audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0,
0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11,
0x1 << 30 | /* chnum_sel */
lane_mask << 24 | /* chnum_sel */
0x1 << 22 | /* clk_inv */
0x0 << 11 /* req_sel, Sync 4 spdifin by which */
);
}
if (channels % 2)
lane = channels / 2 + 1;
else
lane = channels / 2;
for (i = 0; i < lane; i++)
lane_mask |= (1 << i);
audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL0,
0x1 << 30 | 0xf << 24 | 0x1 << 22 | 0x3 << 11,
0x1 << 30 | /* chnum_sel */
lane_mask << 24 | /* chnum_sel */
0x1 << 22 | /* clk_inv */
0x0 << 11 /* req_sel, Sync 4 spdifin by which */
);
/* nonpcm2pcm_th */
audiobus_write(EE_AUDIO_FRHDMIRX_CTRL1, 0xff << 20);
@@ -115,6 +147,22 @@ void frhdmirx_ctrl(int channels, int src)
frhdmirx_enable_irq_bits(channels, src);
}
void frhdmirx_clr_PAO_irq_bits(void)
{
audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL4,
0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK,
0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK);
audiobus_update_bits(EE_AUDIO_FRHDMIRX_CTRL4,
0x1 << INT_PAO_PAPB_MASK | 0x1 << INT_PAO_PCPD_MASK,
0x0 << INT_PAO_PAPB_MASK | 0x0 << INT_PAO_PCPD_MASK);
}
unsigned int frhdmirx_get_ch_status0to31(void)
{
return (unsigned int)audiobus_read(EE_AUDIO_FRHDMIRX_STAT0);
}
unsigned int frhdmirx_get_chan_status_pc(void)
{
unsigned int val;
@@ -122,6 +170,3 @@ unsigned int frhdmirx_get_chan_status_pc(void)
val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1);
return (val >> 16) & 0xff;
}

View File

@@ -17,8 +17,13 @@
#ifndef __FRHDMIRX_HW_H__
#define __FRHDMIRX_HW_H__
#define INT_PAO_PAPB_MASK 24
#define INT_PAO_PCPD_MASK 16
extern void frhdmirx_enable(bool enable);
extern void frhdmirx_src_select(int src);
extern void frhdmirx_ctrl(int channels, int src);
extern void frhdmirx_clr_PAO_irq_bits(void);
extern unsigned int frhdmirx_get_ch_status0to31(void);
extern unsigned int frhdmirx_get_chan_status_pc(void);
#endif

View File

@@ -875,7 +875,7 @@ static struct snd_pcm_ops aml_spdif_ops = {
.mmap = aml_spdif_mmap,
};
#define PREALLOC_BUFFER (128 * 1024)
#define PREALLOC_BUFFER (256 * 1024)
#define PREALLOC_BUFFER_MAX (256 * 1024)
static int aml_spdif_new(struct snd_soc_pcm_runtime *rtd)
{

View File

@@ -358,7 +358,7 @@ static struct snd_pcm_ops aml_tdm_ops = {
.mmap = aml_tdm_mmap,
};
#define PREALLOC_BUFFER (128 * 1024)
#define PREALLOC_BUFFER (256 * 1024)
#define PREALLOC_BUFFER_MAX (256 * 1024)
static int aml_tdm_new(struct snd_soc_pcm_runtime *rtd)
{