mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user