From: Zhe Wang Date: Tue, 9 Jul 2019 09:07:20 +0000 (+0800) Subject: audio: set audio path from frhdmirx through spdifin mode [1/2] X-Git-Tag: hardkernel-4.9.236-104~529 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=742f69cb4aa34d18d71016ca0f125a4407abfe76;p=platform%2Fkernel%2Flinux-amlogic.git audio: set audio path from frhdmirx through spdifin mode [1/2] PD#SWPL-11054 Problem: hdmiin source, audio input is randomly LR invert Solution: set audio path from frhdmirx through spdifin mode Verify: Verified on X301 Change-Id: Ib40d30b8b6d8bc28da69bf9b4f37ae2ef9228761 Signed-off-by: Zhe Wang --- diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c index f48b2fb..cb31828 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c @@ -86,7 +86,7 @@ MODULE_PARM_DESC(hdcp22_on, "\n hdcp22_on\n"); module_param(hdcp22_on, int, 0664); /* test for HBR CTS, audio module can set it to force 8ch */ -int hbr_force_8ch = 1; +int hbr_force_8ch; /* * hdcp14_key_mode:hdcp1.4 key handle method select * NORMAL_MODE:systemcontrol path @@ -2140,7 +2140,7 @@ int hdmirx_audio_init(void) hdmirx_wr_dwc(DWC_PDEC_ACRM_CTRL, data32); /* unsupport HBR serial mode. invalid bit */ - /* hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1); */ + hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1); /* SAO cfg, disable I2S output, no use */ data32 = 0; diff --git a/sound/soc/amlogic/auge/ddr_mngr.c b/sound/soc/amlogic/auge/ddr_mngr.c index 1fa7282..fce113b 100644 --- a/sound/soc/amlogic/auge/ddr_mngr.c +++ b/sound/soc/amlogic/auge/ddr_mngr.c @@ -441,8 +441,8 @@ void aml_toddr_set_format(struct toddr *to, struct toddr_fmt *fmt) reg = calc_toddr_address(EE_AUDIO_TODDR_A_CTRL0, reg_base); aml_audiobus_update_bits(actrl, reg, - 0x7 << 24 | 0x1fff << 3, - fmt->endian << 24 | fmt->type << 13 | + 0x1 << 27 | 0x7 << 24 | 0x1fff << 3, + 0x1 << 27 | fmt->endian << 24 | fmt->type << 13 | fmt->msb << 8 | fmt->lsb << 3); } @@ -695,15 +695,15 @@ static void aml_resample_enable( resample_src_select(to->fifo_id); } - /* resample enable or not */ - resample_enable(p_attach_resample->id, enable); - /* select reample data */ if (to->chipinfo && to->chipinfo->asrc_src_sel_ctrl) aml_toddr_set_resample_ab(to, p_attach_resample->id, enable); else aml_toddr_set_resample(to, enable); + + /* resample enable or disable */ + resample_enable(p_attach_resample->id, enable); } void aml_set_resample(enum resample_idx id, @@ -711,7 +711,6 @@ void aml_set_resample(enum resample_idx id, { struct toddr_attach *p_attach_resample; struct toddr *to; - bool update_running = false; if (id == RESAMPLE_A) p_attach_resample = &attach_resample_a; @@ -730,26 +729,7 @@ void aml_set_resample(enum resample_idx id, goto exit; } - if (enable) { - if ((p_attach_resample->status == DISABLED) - || (p_attach_resample->status == READY)) { - - if (!to) { - p_attach_resample->status = READY; - } else { - p_attach_resample->status = RUNNING; - update_running = true; - pr_info("Capture with resample\n"); - } - } - } else { - if (p_attach_resample->status == RUNNING) - update_running = true; - - p_attach_resample->status = DISABLED; - } - - if (update_running && to) + if (p_attach_resample->status == RUNNING) aml_resample_enable(to, p_attach_resample, enable); exit: @@ -770,18 +750,19 @@ static void aml_check_resample(struct toddr *to, bool enable) start_check: is_module_resample = false; - if (p_attach_resample->enable - && (to->src == p_attach_resample->attach_module)) + if (to->src == p_attach_resample->attach_module) is_module_resample = true; - /* resample in enable */ if (is_module_resample) { + /* save toddr status */ if (enable) p_attach_resample->status = RUNNING; else p_attach_resample->status = DISABLED; - aml_resample_enable(to, p_attach_resample, enable); + /*if disable toddr, disable attached resampler*/ + if (p_attach_resample->enable) + aml_resample_enable(to, p_attach_resample, enable); } if ((!resample_b_check) diff --git a/sound/soc/amlogic/auge/extn.c b/sound/soc/amlogic/auge/extn.c index f95afa5..97f7cc8 100644 --- a/sound/soc/amlogic/auge/extn.c +++ b/sound/soc/amlogic/auge/extn.c @@ -50,6 +50,11 @@ #define DYNC_KCNTL_CNT 2 +enum { + HDMIRX_MODE_SPDIFIN = 0, + HDMIRX_MODE_PAO = 1, +}; + struct extn_chipinfo { /* try to check papb before fetch pcpd * no nonpcm2pcm irq for tl1 @@ -147,27 +152,24 @@ static irqreturn_t extn_ddr_isr(int irq, void *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); - int timeout_thres = 5; - -#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI - int sample_rate_index = get_hdmi_sample_rate_index(); - - /*192K audio*/ - if (sample_rate_index == 7) - timeout_thres = 10; - else - timeout_thres = 5; -#endif 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) { + /* check pcm or nonpcm for PAO*/ + if (p_extn->hdmirx_mode == HDMIRX_MODE_PAO) { + int timeout_thres = 5; +#ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI + int sample_rate_index = get_hdmi_sample_rate_index(); + + /*192K audio*/ + if (sample_rate_index == 7) + timeout_thres = 10; + else + timeout_thres = 5; +#endif if (p_extn->frhdmirx_last_cnt == p_extn->frhdmirx_cnt) { p_extn->frhdmirx_same_cnt++; @@ -183,6 +185,8 @@ static irqreturn_t extn_ddr_isr(int irq, void *devid) p_extn->nonpcm_flag = true; frhdmirx_clr_PAO_irq_bits(); } + } else { + frhdmirx_clr_SPDIF_irq_bits(); } return IRQ_HANDLED; @@ -260,8 +264,7 @@ static int extn_close(struct snd_pcm_substream *substream) if (toddr_src_get() == FRHDMIRX) { frhdmirx_nonpcm2pcm_clr_reset(p_extn); - if (p_extn->hdmirx_mode == 1) - frhdmirx_clr_PAO_irq_bits(); + frhdmirx_clr_all_irq_bits(); free_irq(p_extn->irq_frhdmirx, p_extn); } } @@ -496,20 +499,26 @@ static int extn_dai_prepare( */ /* fratv_src_select(1); */ } else if (src == FRHDMIRX) { - if (p_extn->hdmirx_mode) { /* PAO */ - if (bit_depth == 32) - toddr_type = 3; - else if (bit_depth == 24) - toddr_type = 4; - else - toddr_type = 0; + if (bit_depth == 32) + toddr_type = 3; + else if (bit_depth == 24) + toddr_type = 4; + else + toddr_type = 0; + if (p_extn->hdmirx_mode == HDMIRX_MODE_PAO) { /* PAO */ msb = 28 - 1 - 4; if (bit_depth == 16) lsb = 24 - bit_depth; else lsb = 4; + } else { /* SPDIFIN */ + msb = 28 - 1; + if (bit_depth <= 24) + lsb = 28 - bit_depth; + else + lsb = 4; } frhdmirx_ctrl(runtime->channels, p_extn->hdmirx_mode); @@ -812,7 +821,7 @@ static int hdmiin_check_audio_type(struct extn *p_extn) int audio_type = 0; int i; - if (!p_extn->nonpcm_flag) + if (!p_extn->nonpcm_flag && p_extn->hdmirx_mode) return audio_type; for (i = 0; i < total_num; i++) { @@ -935,9 +944,9 @@ static const struct snd_kcontrol_new extn_controls[] = { aml_set_atmos_audio_edid), SOC_ENUM_EXT("HDMIIN Audio Type", - hdmirx_audio_type_enum, - hdmirx_audio_type_get_enum, - NULL), + hdmirx_audio_type_enum, + hdmirx_audio_type_get_enum, + NULL), #endif }; @@ -1014,8 +1023,8 @@ static int extn_platform_probe(struct platform_device *pdev) /* Default ARC SRC */ p_extn->arc_src = 1; - /* Default: PAO mode */ - p_extn->hdmirx_mode = 1; + /* Default: SPDIFIN mode */ + p_extn->hdmirx_mode = HDMIRX_MODE_SPDIFIN; ret = devm_snd_soc_register_component(&pdev->dev, &extn_component, diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.c b/sound/soc/amlogic/auge/frhdmirx_hw.c index 1dd0593..6f2846b 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.c +++ b/sound/soc/amlogic/auge/frhdmirx_hw.c @@ -51,12 +51,7 @@ void frhdmirx_src_select(int src) static void frhdmirx_enable_irq_bits(int channels, int src) { - int lane, int_bits = 0, i; - - if (channels % 2) - lane = channels / 2 + 1; - else - lane = channels / 2; + unsigned int int_bits = 0; /* interrupt bits */ if (src) { /* PAO mode */ @@ -66,78 +61,59 @@ static void frhdmirx_enable_irq_bits(int channels, int src) ); } else { /* SPDIF Lane */ int lane_irq_bits = (0x1 << 7 | /* lane: find papb */ - 0x1 << 6 | /* 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 */ ); + int lane, i; + + lane = (channels % 2) ? (channels / 2 + 1) : (channels / 2); for (i = 0; i < lane; i++) - int_bits |= (lane_irq_bits << i); + int_bits |= (lane_irq_bits << 8 * i); } + + int_bits |= audiobus_read(EE_AUDIO_FRHDMIRX_CTRL2); audiobus_write(EE_AUDIO_FRHDMIRX_CTRL2, int_bits); } -void frhdmirx_clr_irq_bits(int channels, int src) +void frhdmirx_clr_all_irq_bits(void) { - 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); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, 0xffffffff); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL3, 0x0); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, 0xffffffff); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, 0x0); } void frhdmirx_ctrl(int channels, int src) { - int lane, lane_mask = 0, i; - /* PAO mode */ if (src) { audiobus_write(EE_AUDIO_FRHDMIRX_CTRL0, 0x1 << 22 | /* capture input by fall edge*/ 0x1 << 8 | /* start detect PAPB */ + 0x1 << 7 | /* add channel num */ 0x4 << 4 /* chan status sel: pao pc/pd value */ ); } else { - if (channels % 2) - lane = channels / 2 + 1; - else - lane = channels / 2; + int lane, lane_mask = 0, i; + lane = (channels % 2) ? (channels / 2 + 1) : (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 | 0xf << 24 | 0x1 << 22 | + 0x3 << 11 | 0x1 << 8 | 0x1 << 7 | 0x7 << 0, 0x1 << 30 | /* chnum_sel */ lane_mask << 24 | /* chnum_sel */ 0x1 << 22 | /* clk_inv */ - 0x0 << 11 /* req_sel, Sync 4 spdifin by which */ + 0x0 << 11 | /* req_sel, Sync 4 spdifin by which */ + 0x1 << 8 | /* start detect PAPB */ + 0x1 << 7 | /* add channel num*/ + 0x6 << 0 /* channel status*/ ); } /* nonpcm2pcm_th */ @@ -158,6 +134,35 @@ void frhdmirx_clr_PAO_irq_bits(void) 0x0 << INT_PAO_PAPB_MASK | 0x0 << INT_PAO_PCPD_MASK); } +void frhdmirx_clr_SPDIF_irq_bits(void) +{ + unsigned int value = audiobus_read(EE_AUDIO_FRHDMIRX_STAT0); + unsigned int clr_mask = audiobus_read(EE_AUDIO_FRHDMIRX_CTRL4); + unsigned int reg = 0; + int i; + + reg = clr_mask | value; + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, reg); + + reg = clr_mask & (~value); + audiobus_write(EE_AUDIO_FRHDMIRX_CTRL4, reg); + + /*compressed audio only transfer through lane0*/ + for (i = 0; i < 1; i++) { + /*nonpcm2pcm irq, clear papb/pcpd/nonpcm*/ + if (value & (0x20 << 8 * i)) { + audiobus_update_bits( + EE_AUDIO_FRHDMIRX_CTRL3, + 0xf << 8 * i, 0xf << 8 * i); + audiobus_update_bits( + EE_AUDIO_FRHDMIRX_CTRL3, + 0xf << 8 * i, 0x0 << 8 * i); + pr_info("raw to pcm change: irq status:%x, lane: %d\n", + value, i); + } + } +} + unsigned int frhdmirx_get_ch_status0to31(void) { return (unsigned int)audiobus_read(EE_AUDIO_FRHDMIRX_STAT0); @@ -170,3 +175,4 @@ unsigned int frhdmirx_get_chan_status_pc(void) val = audiobus_read(EE_AUDIO_FRHDMIRX_STAT1); return (val >> 16) & 0xff; } + diff --git a/sound/soc/amlogic/auge/frhdmirx_hw.h b/sound/soc/amlogic/auge/frhdmirx_hw.h index 7c83dd0..6b336cd 100644 --- a/sound/soc/amlogic/auge/frhdmirx_hw.h +++ b/sound/soc/amlogic/auge/frhdmirx_hw.h @@ -20,10 +20,13 @@ #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); +void frhdmirx_enable(bool enable); +void frhdmirx_src_select(int src); +void frhdmirx_ctrl(int channels, int src); +void frhdmirx_clr_PAO_irq_bits(void); +void frhdmirx_clr_SPDIF_irq_bits(void); +unsigned int frhdmirx_get_ch_status0to31(void); +unsigned int frhdmirx_get_chan_status_pc(void); +void frhdmirx_clr_all_irq_bits(void); + #endif diff --git a/sound/soc/amlogic/auge/resample.c b/sound/soc/amlogic/auge/resample.c index c4cd6c1..41905cf 100644 --- a/sound/soc/amlogic/auge/resample.c +++ b/sound/soc/amlogic/auge/resample.c @@ -143,12 +143,6 @@ static int resample_clk_set(struct audioresample *p_resample) return ret; } -static void audio_resample_init(struct audioresample *p_resample) -{ - aml_set_resample(p_resample->id, p_resample->enable, - p_resample->resample_module); -} - static int audio_resample_set( struct audioresample *p_resample, bool enable, int rate) @@ -158,7 +152,9 @@ static int audio_resample_set( p_resample->enable = enable; p_resample->out_rate = rate; - audio_resample_init(p_resample); + aml_set_resample( + p_resample->id, p_resample->enable, + p_resample->resample_module); return 0; } diff --git a/sound/soc/amlogic/auge/resample_hw.c b/sound/soc/amlogic/auge/resample_hw.c index f5d4d43..0ebbece 100644 --- a/sound/soc/amlogic/auge/resample_hw.c +++ b/sound/soc/amlogic/auge/resample_hw.c @@ -45,6 +45,11 @@ void resample_enable(enum resample_idx id, bool enable) int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; + /*don't change this flow*/ + audiobus_update_bits( + reg, 0x1 << 31 | 0x1 << 28, + 0 << 31 | 0x0 << 28); + audiobus_update_bits(reg, 0x1 << 31, 1 << 31); @@ -90,7 +95,7 @@ int resample_disable(enum resample_idx id) int offset = EE_AUDIO_RESAMPLEB_CTRL0 - EE_AUDIO_RESAMPLEA_CTRL0; int reg = EE_AUDIO_RESAMPLEA_CTRL0 + offset * id; - audiobus_write(reg, 0); + audiobus_update_bits(reg, 0x1 << 28, 0 << 28); return 0; } @@ -116,7 +121,7 @@ int resample_set_hw_param(enum resample_idx id, offset = EE_AUDIO_RESAMPLEB_CTRL2 - EE_AUDIO_RESAMPLEA_CTRL2; reg = EE_AUDIO_RESAMPLEA_CTRL2 + offset * id; - audiobus_update_bits(reg, 1 << 25, 1 << 25); + audiobus_update_bits(reg, 3 << 26 | 1 << 25, 3 << 26 | 1 << 25); resample_set_hw_pause_thd(id, 128); return 0;