Fix lockup in aud->clkgen notification
This commit is contained in:
@@ -804,6 +804,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk,
|
|||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
/* Notify clockgen of new mCLk */
|
/* Notify clockgen of new mCLk */
|
||||||
c_mclk_change <: mClk;
|
c_mclk_change <: mClk;
|
||||||
|
c_mclk_change <: curFreq;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "xua_commands.h"
|
#include "xua_commands.h"
|
||||||
#include "xua_clocking.h"
|
#include "xua_clocking.h"
|
||||||
|
|
||||||
|
#include <stdio.h> // TODO DEV ONLY - DELME
|
||||||
|
|
||||||
#ifdef __XS3A__
|
#ifdef __XS3A__
|
||||||
#define USE_SW_PLL 1
|
#define USE_SW_PLL 1
|
||||||
@@ -231,7 +232,7 @@ static inline int validSamples(Counter &counter, int clockIndex)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
void InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
unsigned InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
||||||
{
|
{
|
||||||
/* Autogenerated SDM App PLL setup by dco_model.py using 22.5792_1M profile */
|
/* Autogenerated SDM App PLL setup by dco_model.py using 22.5792_1M profile */
|
||||||
/* Input freq: 24000000
|
/* Input freq: 24000000
|
||||||
@@ -270,7 +271,7 @@ void InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
|||||||
const uint32_t app_pll_div_reg[2] = {APP_PLL_DIV_REG_22, APP_PLL_DIV_REG_24};
|
const uint32_t app_pll_div_reg[2] = {APP_PLL_DIV_REG_22, APP_PLL_DIV_REG_24};
|
||||||
const uint32_t app_pll_frac_reg[2] = {APP_PLL_FRAC_REG_22, APP_PLL_FRAC_REG_24};
|
const uint32_t app_pll_frac_reg[2] = {APP_PLL_FRAC_REG_22, APP_PLL_FRAC_REG_24};
|
||||||
const uint32_t sw_pll_sdm_ctrl_mid[2] = {SW_PLL_SDM_CTRL_MID_22, SW_PLL_SDM_CTRL_MID_24};
|
const uint32_t sw_pll_sdm_ctrl_mid[2] = {SW_PLL_SDM_CTRL_MID_22, SW_PLL_SDM_CTRL_MID_24};
|
||||||
// const uint32_t sw_pll_sdm_rate[2] = {SW_PLL_SDM_RATE_22, SW_PLL_SDM_RATE_24};
|
const uint32_t sw_pll_sdm_rate[2] = {SW_PLL_SDM_RATE_22, SW_PLL_SDM_RATE_24};
|
||||||
|
|
||||||
const int clkIndex = mClk == MCLK_48 ? 1 : 0;
|
const int clkIndex = mClk == MCLK_48 ? 1 : 0;
|
||||||
|
|
||||||
@@ -289,29 +290,93 @@ void InitSWPLL(sw_pll_state_t &sw_pll, unsigned mClk)
|
|||||||
|
|
||||||
|
|
||||||
printstr("Init sw_pll: "); printuintln(mClk);
|
printstr("Init sw_pll: "); printuintln(mClk);
|
||||||
|
|
||||||
|
return (XS1_TIMER_HZ / sw_pll_sdm_rate[clkIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_sw_pll_control(sw_pll_state_t sw_pll, unsigned short mclk_time_stamp, chanend c_sigma_delta)
|
void do_sw_pll_control( sw_pll_state_t sw_pll,
|
||||||
|
unsigned short mclk_time_stamp,
|
||||||
|
unsigned mclks_per_sample,
|
||||||
|
chanend c_sigma_delta,
|
||||||
|
int receivedSamples)
|
||||||
{
|
{
|
||||||
|
static unsigned short last_mclk_time_stamp = 0;
|
||||||
static unsigned count = 0;
|
static unsigned count = 0;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
const unsigned expected_mclk_inc = mclks_per_sample * receivedSamples;
|
||||||
|
const unsigned short expected_mclk_count = (last_mclk_time_stamp + expected_mclk_inc) & 0xffff;
|
||||||
|
|
||||||
|
short f_error = (int)mclk_time_stamp - (int)expected_mclk_count;
|
||||||
|
|
||||||
|
|
||||||
if(count == 30)
|
if(count == 30)
|
||||||
{
|
{
|
||||||
printuintln(mclk_time_stamp);
|
//calc mclk inc
|
||||||
|
|
||||||
|
outuint(c_sigma_delta, (unsigned) (1000000 + f_error));
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_mclk_time_stamp = mclk_time_stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SigmaDeltaTask(chanend c_sigma_delta){
|
void SigmaDeltaTask(chanend c_sigma_delta, unsigned sdm_interval){
|
||||||
|
/* Zero is an invalid number and the SDM will not write the frac reg until
|
||||||
|
the first control value has been received. This avoids issues with
|
||||||
|
channel lockup if two tasks (eg. init and SDM) try to write at the same time. */
|
||||||
|
|
||||||
int dco_setting = 0;
|
int dco_setting = 0;
|
||||||
|
sw_pll_sdm_state_t sdm_state;
|
||||||
|
sw_pll_init_sigma_delta(&sdm_state);
|
||||||
|
|
||||||
|
tileref_t this_tile = get_local_tile_id();
|
||||||
|
|
||||||
|
timer tmr;
|
||||||
|
int32_t time_trigger;
|
||||||
|
tmr :> time_trigger;
|
||||||
|
int send_ack_once = 1;
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
c_sigma_delta :> dco_setting;
|
/* Poll for new SDM control value */
|
||||||
printstr("sigma-delta got: "); printintln(dco_setting);
|
unsigned tmp;
|
||||||
if(dco_setting == 0)
|
select
|
||||||
{
|
{
|
||||||
c_sigma_delta <: 0; /* Send ACK */
|
case inuint_byref(c_sigma_delta, tmp):
|
||||||
|
dco_setting = (int32_t)tmp;
|
||||||
|
printstr("sigma-delta got: "); printintln(dco_setting);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Do nothing & fall-through
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until the timer value has been reached
|
||||||
|
This implements a timing barrier and keeps
|
||||||
|
the loop rate constant. */
|
||||||
|
select
|
||||||
|
{
|
||||||
|
case tmr when timerafter(time_trigger) :> int _:
|
||||||
|
time_trigger += sdm_interval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do not write to the frac reg until we get out first
|
||||||
|
control value. This will avoid the writing of the
|
||||||
|
frac reg from two different threads which may cause
|
||||||
|
a channel deadlock. */
|
||||||
|
if(dco_setting != 0)
|
||||||
|
{
|
||||||
|
sw_pll_do_sigma_delta(&sdm_state, this_tile, dco_setting);
|
||||||
|
send_ack_once = 1;
|
||||||
|
}
|
||||||
|
else if(send_ack_once)
|
||||||
|
{
|
||||||
|
/* Send ACK once to synchrnoise with clockgen signalling it's OK to reconfig */
|
||||||
|
outuint(c_sigma_delta, 0); /* Send ACK to say reg writes have ceased */
|
||||||
|
send_ack_once = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,8 +384,8 @@ void SigmaDeltaTask(chanend c_sigma_delta){
|
|||||||
|
|
||||||
void disable_sigma_delta(chanend c_sigma_delta)
|
void disable_sigma_delta(chanend c_sigma_delta)
|
||||||
{
|
{
|
||||||
c_sigma_delta <: 0; /* Stops SD */
|
outuint(c_sigma_delta, 0); /* Stops SD */
|
||||||
c_sigma_delta :> int _; /* Wait for ACK so we know reg write is complete */
|
inuint(c_sigma_delta); /* Wait for ACK so we know reg write is complete */
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -360,6 +425,8 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
timer t_external;
|
timer t_external;
|
||||||
unsigned selected_mclk_rate = 0;
|
unsigned selected_mclk_rate = 0;
|
||||||
|
unsigned selected_sample_rate = 0;
|
||||||
|
unsigned mclks_per_sample = 0;
|
||||||
unsigned short mclk_time_stamp = 0;
|
unsigned short mclk_time_stamp = 0;
|
||||||
/* Get MCLK count */
|
/* Get MCLK count */
|
||||||
asm volatile(" getts %0, res[%1]" : "=r" (mclk_time_stamp) : "r" (p_for_mclk_count_aud));
|
asm volatile(" getts %0, res[%1]" : "=r" (mclk_time_stamp) : "r" (p_for_mclk_count_aud));
|
||||||
@@ -457,11 +524,11 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
chan c_sigma_delta;
|
chan c_sigma_delta;
|
||||||
sw_pll_state_t sw_pll;
|
sw_pll_state_t sw_pll;
|
||||||
InitSWPLL(sw_pll, MCLK_48);
|
unsigned sdm_interval = InitSWPLL(sw_pll, MCLK_48);
|
||||||
|
|
||||||
par
|
par
|
||||||
{
|
{
|
||||||
SigmaDeltaTask(c_sigma_delta);
|
SigmaDeltaTask(c_sigma_delta, sdm_interval);
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
@@ -635,10 +702,14 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
|
|
||||||
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
|
||||||
case c_mclk_change :> selected_mclk_rate:
|
case c_mclk_change :> selected_mclk_rate:
|
||||||
|
c_mclk_change :> selected_sample_rate;
|
||||||
|
mclks_per_sample = selected_mclk_rate / selected_sample_rate;
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
printstr("c_mclk_change: "); printuintln(selected_mclk_rate);
|
printstr("c_mclk_change: "); printuintln(selected_mclk_rate);
|
||||||
disable_sigma_delta(c_sigma_delta); /* Blocks until SD is idle */
|
disable_sigma_delta(c_sigma_delta); /* Blocks until SDM is idle */
|
||||||
InitSWPLL(sw_pll, selected_mclk_rate);
|
InitSWPLL(sw_pll, selected_mclk_rate);
|
||||||
|
outuint(c_sigma_delta, sw_pll.sdm_state.ctrl_mid_point); /* Send ctrl mid point to enable SDM */
|
||||||
|
printstr("swpll int'd\n");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -684,12 +755,14 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
if(spdifSamps > MAX_SPDIF_SAMPLES-1)
|
if(spdifSamps > MAX_SPDIF_SAMPLES-1)
|
||||||
{
|
{
|
||||||
spdifOverflow = 1;
|
spdifOverflow = 1;
|
||||||
|
printstr("spo+\n"); // DELME
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for coming out of under flow */
|
/* Check for coming out of under flow */
|
||||||
if(spdifUnderflow && (spdifSamps >= (MAX_SPDIF_SAMPLES >> 1)))
|
if(spdifUnderflow && (spdifSamps >= (MAX_SPDIF_SAMPLES >> 1)))
|
||||||
{
|
{
|
||||||
spdifUnderflow = 0;
|
spdifUnderflow = 0;
|
||||||
|
printstr("spu-\n"); // DELME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -719,7 +792,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
timeNextEdge = spdifRxTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
||||||
|
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
do_sw_pll_control(sw_pll, mclk_time_stamp, c_sigma_delta);
|
do_sw_pll_control(sw_pll, mclk_time_stamp, mclks_per_sample, c_sigma_delta, spdifCounters.receivedSamples);
|
||||||
#else
|
#else
|
||||||
/* Toggle edge */
|
/* Toggle edge */
|
||||||
i_pll_ref.toggle_timed(1);
|
i_pll_ref.toggle_timed(1);
|
||||||
@@ -829,7 +902,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
timeNextEdge = adatReceivedTime + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN;
|
||||||
|
|
||||||
#if USE_SW_PLL
|
#if USE_SW_PLL
|
||||||
do_sw_pll_control(sw_pll, mclk_time_stamp, c_sigma_delta);
|
do_sw_pll_control(sw_pll, mclk_time_stamp, mclks_per_sample, c_sigma_delta, adatCounters.receivedSamples);
|
||||||
#else
|
#else
|
||||||
/* Toggle edge */
|
/* Toggle edge */
|
||||||
i_pll_ref.toggle_timed(1);
|
i_pll_ref.toggle_timed(1);
|
||||||
@@ -876,6 +949,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
{
|
{
|
||||||
/* We're out of S/PDIF samples, mark underflow condition */
|
/* We're out of S/PDIF samples, mark underflow condition */
|
||||||
spdifUnderflow = 1;
|
spdifUnderflow = 1;
|
||||||
|
printstr("spu-\n"); // DELME
|
||||||
spdifLeft = 0;
|
spdifLeft = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,6 +958,7 @@ void clockGen ( streaming chanend ?c_spdif_rx,
|
|||||||
if(spdifOverflow && (spdifSamps < (MAX_SPDIF_SAMPLES>>1)))
|
if(spdifOverflow && (spdifSamps < (MAX_SPDIF_SAMPLES>>1)))
|
||||||
{
|
{
|
||||||
spdifOverflow = 0;
|
spdifOverflow = 0;
|
||||||
|
printstr("spo-\n"); // DELME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user