mirror of
https://github.com/marqs85/ossc.git
synced 2024-12-29 09:32:45 +00:00
make pll_reconfig more robust
This commit is contained in:
parent
8e7236dc00
commit
85c295c5e2
@ -26,7 +26,9 @@ typedef union {
|
||||
struct {
|
||||
alt_u8 reset:1;
|
||||
alt_u8 update:1;
|
||||
alt_u32 pll_reconfig_rsv:29;
|
||||
alt_u8 t_config_id:4;
|
||||
alt_u32 pll_reconfig_rsv:21;
|
||||
alt_u8 c_config_id:4;
|
||||
alt_u8 busy:1;
|
||||
} __attribute__((packed, __may_alias__));
|
||||
alt_u32 data;
|
||||
|
@ -56,10 +56,12 @@ reg [1:0] state;
|
||||
reg scan_shift;
|
||||
reg scandone_prev;
|
||||
reg configupdate_pre;
|
||||
reg [7:0] ctr;
|
||||
reg [7:0] shift_ctr;
|
||||
|
||||
wire pll_reset = pll_config_status[0];
|
||||
wire start_update = pll_config_status[1];
|
||||
wire [3:0] t_config_id = pll_config_status[5:2];
|
||||
wire [3:0] c_config_id = pll_config_status[30:27];
|
||||
wire config_busy = pll_config_status[31];
|
||||
|
||||
assign areset = pll_reset | areset_strobe;
|
||||
@ -141,7 +143,7 @@ begin
|
||||
if (start_update) begin
|
||||
pll_config_status[31] <= 1'b1;
|
||||
scanclkena <= 1'b1;
|
||||
ctr <= PLL_CONFIG_DATA_BITS;
|
||||
shift_ctr <= PLL_CONFIG_DATA_BITS;
|
||||
state <= STATE_SHIFT;
|
||||
end else begin
|
||||
pll_config_status[31] <= 1'b0;
|
||||
@ -150,22 +152,23 @@ begin
|
||||
STATE_SHIFT:
|
||||
begin
|
||||
scan_shift <= 1'b1;
|
||||
if (ctr > 0) begin
|
||||
ctr <= ctr - 1'b1;
|
||||
if (shift_ctr > 0) begin
|
||||
shift_ctr <= shift_ctr - 1'b1;
|
||||
end else begin
|
||||
scan_shift <= 1'b0;
|
||||
scanclkena <= 1'b0;
|
||||
configupdate_pre <= 1'b1;
|
||||
ctr <= 8'hff;
|
||||
state <= STATE_WAITRESP;
|
||||
end
|
||||
end
|
||||
STATE_WAITRESP:
|
||||
begin
|
||||
configupdate_pre <= 1'b0;
|
||||
ctr <= ctr - 1'b1;
|
||||
if (scandone_prev | (ctr == 8'h0)) begin
|
||||
if (pll_reset) begin
|
||||
state <= STATE_IDLE;
|
||||
end else if (scandone_prev) begin
|
||||
areset_strobe <= 1'b1;
|
||||
pll_config_status[30:27] <= t_config_id;
|
||||
state <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
@ -106,7 +106,7 @@ wire osd_enable = osd_enable_pre & ~lt_active;
|
||||
wire [10:0] xpos, xpos_sc, xpos_vg;
|
||||
wire [10:0] ypos, ypos_sc, ypos_vg;
|
||||
|
||||
wire pll_areset, pll_scanclk, pll_scanclkena, pll_configupdate, pll_scandata, pll_scandone;
|
||||
wire pll_areset, pll_scanclk, pll_scanclkena, pll_configupdate, pll_scandata, pll_scandone, pll_activeclock;
|
||||
|
||||
|
||||
// Latch inputs from TVP7002 (synchronized to PCLK_in)
|
||||
@ -236,7 +236,7 @@ sys sys_inst(
|
||||
.i2c_opencores_1_export_sda_pad_io (SD_CMD),
|
||||
.i2c_opencores_1_export_spi_miso_pad_i (SD_DAT[0]),
|
||||
.pio_0_sys_ctrl_out_export (sys_ctrl),
|
||||
.pio_1_controls_in_export ({ir_code_cnt, 5'b00000, HDMI_TX_MODE_LL, btn_LL, ir_code}),
|
||||
.pio_1_controls_in_export ({ir_code_cnt, 4'b0000, pll_activeclock, HDMI_TX_MODE_LL, btn_LL, ir_code}),
|
||||
.sc_config_0_sc_if_sc_status_i ({vsync_flag, 2'b00, vmax_tvp, fpga_vsyncgen, 4'h0, ilace_flag, vmax}),
|
||||
.sc_config_0_sc_if_sc_status2_i ({12'h000, pcnt_frame}),
|
||||
.sc_config_0_sc_if_lt_status_i ({lt_finished, 3'h0, lt_stb_result, lt_lat_result}),
|
||||
@ -300,7 +300,8 @@ scanconverter scanconverter_inst (
|
||||
.pll_scanclkena (pll_scanclkena),
|
||||
.pll_configupdate (pll_configupdate),
|
||||
.pll_scandata (pll_scandata),
|
||||
.pll_scandone (pll_scandone)
|
||||
.pll_scandone (pll_scandone),
|
||||
.pll_activeclock (pll_activeclock)
|
||||
);
|
||||
|
||||
ir_rcv ir0 (
|
||||
|
@ -118,7 +118,8 @@ module scanconverter (
|
||||
input pll_scanclkena,
|
||||
input pll_configupdate,
|
||||
input pll_scandata,
|
||||
output pll_scandone
|
||||
output pll_scandone,
|
||||
output pll_activeclock
|
||||
);
|
||||
|
||||
//clock-related signals and registers
|
||||
@ -126,7 +127,6 @@ wire pclk_act;
|
||||
wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_5x;
|
||||
wire [1:0] pclk_mux_sel;
|
||||
wire pll_lock;
|
||||
wire pll_activeclock;
|
||||
reg pll_clkswitch;
|
||||
|
||||
//RGB signals®isters: 8 bits per component -> 16.7M colors
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,7 @@ alt_u8 stable_frames;
|
||||
alt_u8 update_cur_vm;
|
||||
|
||||
alt_u8 profile_sel, profile_sel_menu, input_profiles[AV_LAST], lt_sel, def_input, profile_link, lcd_bl_timeout;
|
||||
alt_u8 osd_enable, osd_enable_pre=1, osd_status_timeout, osd_status_timeout_pre;
|
||||
alt_u8 osd_enable, osd_enable_pre=1, osd_status_timeout, osd_status_timeout_pre=1;
|
||||
alt_u8 auto_input, auto_av1_ypbpr, auto_av2_ypbpr = 1, auto_av3_ypbpr;
|
||||
|
||||
char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
|
||||
@ -97,9 +97,9 @@ alt_u32 read_it2(alt_u32 regaddr);
|
||||
// 8. Compare your MIF/HEX to the captured scan chain and update it accordingly
|
||||
// 9. Dump the updated scan chain data to an array like below (last 16 bits are 0)
|
||||
// 10. PLL can be then reconfigured with custom pll_reconfig as shown in program_mode()
|
||||
const alt_u32 pll_config_default_data[] = {0x0d806000, 0x00402010, 0x08040220, 0x00004022, 0x00000000};
|
||||
const alt_u32 pll_config_2x_5x_data[] = {0x0dc06000, 0x00783c11, 0x070180e0, 0x0000180e, 0x00000000};
|
||||
const alt_u32 pll_config_3x_4x_data[] = {0x0d806000, 0x00301804, 0x02014060, 0x00001406, 0x00000000};
|
||||
const pll_config_t pll_configs[] = { {{0x0d806000, 0x00402010, 0x08040220, 0x00004022, 0x00000000}}, // 1x, 1x (default)
|
||||
{{0x0dc06000, 0x00783c11, 0x070180e0, 0x0000180e, 0x00000000}}, // 2x, 5x
|
||||
{{0x0d806000, 0x00301804, 0x02014060, 0x00001406, 0x00000000}} }; // 3x, 4x
|
||||
|
||||
volatile sc_regs *sc = (volatile sc_regs*)SC_CONFIG_0_BASE;
|
||||
volatile osd_regs *osd = (volatile osd_regs*)OSD_GENERATOR_0_BASE;
|
||||
@ -165,6 +165,41 @@ inline void TX_enable(tx_mode_t mode)
|
||||
SetAVMute(FALSE);
|
||||
}
|
||||
|
||||
void pll_reconfigure(alt_u8 id)
|
||||
{
|
||||
if ((id < sizeof(pll_configs)/sizeof(pll_config_t)) && (id != pll_reconfig->pll_config_status.c_config_id)) {
|
||||
memcpy((void*)pll_reconfig->pll_config_data.data, pll_configs[id].data, sizeof(pll_config_t));
|
||||
pll_reconfig->pll_config_status.t_config_id = id;
|
||||
|
||||
printf("Reconfiguring PLL to config %u\n", id);
|
||||
|
||||
// Try switching to fixed reference clock as otherwise reconfig may hang or corrupt configuration
|
||||
if (cm.avinput != AV_TESTPAT) {
|
||||
sys_ctrl &= ~VIDGEN_OFF;
|
||||
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
// Do not reconfigure if clock switch failed
|
||||
if ((IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PLL_ACTIVECLK_MASK) == 0) {
|
||||
// reset state machine if previous reconfigure hanged (should not occur with stable refclk)
|
||||
if (pll_reconfig->pll_config_status.busy) {
|
||||
pll_reconfig->pll_config_status.reset = 1;
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
pll_reconfig->pll_config_status.reset = 0;
|
||||
pll_reconfig->pll_config_status.update = 1;
|
||||
usleep(10);
|
||||
}
|
||||
|
||||
if (cm.avinput != AV_TESTPAT) {
|
||||
sys_ctrl |= VIDGEN_OFF;
|
||||
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_lpf(alt_u8 lpf)
|
||||
{
|
||||
alt_u32 pclk;
|
||||
@ -330,6 +365,9 @@ status_t get_status(tvp_sync_input_t syncinput)
|
||||
if ((tc.s400p_mode != cm.cc.s400p_mode) && (video_modes[cm.id].v_total == 449))
|
||||
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
|
||||
|
||||
if (cm.pll_config != pll_reconfig->pll_config_status.c_config_id)
|
||||
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
|
||||
|
||||
if (update_cur_vm) {
|
||||
cm.h_mult_total = (video_modes[cm.id].h_total*cm.sample_mult) + ((cm.sample_mult*video_modes[cm.id].h_total_adj*5 + 50) / 100);
|
||||
tvp_setup_hpll(cm.h_mult_total, clkcnt, cm.cc.tvp_hpll2x && (video_modes[cm.id].flags & MODE_PLLDIVBY2));
|
||||
@ -576,7 +614,7 @@ void update_sc_config()
|
||||
// Configure TVP7002 and scan converter logic based on the video mode
|
||||
void program_mode()
|
||||
{
|
||||
alt_u8 h_syncinlen, v_syncinlen, hdmitx_pclk_level, osd_x_size, osd_y_size, pll_config;
|
||||
alt_u8 h_syncinlen, v_syncinlen, hdmitx_pclk_level, osd_x_size, osd_y_size;
|
||||
alt_u32 h_hz, v_hz_x100, h_synclen_px;
|
||||
|
||||
// Mark as stable (needed after sync up to avoid unnecessary mode switch)
|
||||
@ -629,30 +667,21 @@ void program_mode()
|
||||
set_csc(cm.cc.ypbpr_cs);
|
||||
cm.sample_sel = tvp_set_hpll_phase(video_modes[cm.id].sampler_phase, cm.sample_mult);
|
||||
|
||||
pll_reconfig->pll_config_status.reset = (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X);
|
||||
|
||||
switch (cm.fpga_vmultmode) {
|
||||
case FPGA_V_MULTMODE_2X:
|
||||
case FPGA_V_MULTMODE_5X:
|
||||
pll_config = PLL_CONFIG_2X_5X;
|
||||
cm.pll_config = PLL_CONFIG_2X_5X;
|
||||
break;
|
||||
case FPGA_V_MULTMODE_3X:
|
||||
case FPGA_V_MULTMODE_4X:
|
||||
pll_config = PLL_CONFIG_3X_4X;
|
||||
cm.pll_config = PLL_CONFIG_3X_4X;
|
||||
break;
|
||||
default:
|
||||
pll_config = cm.pll_config;
|
||||
break;
|
||||
}
|
||||
|
||||
while (pll_reconfig->pll_config_status.busy) {}
|
||||
pll_reconfig->pll_config_status.reset = (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X);
|
||||
if (cm.pll_config != pll_config) {
|
||||
if (pll_config == PLL_CONFIG_2X_5X)
|
||||
memcpy((void*)pll_reconfig->pll_config_data.data, pll_config_2x_5x_data, sizeof(pll_config_2x_5x_data));
|
||||
else
|
||||
memcpy((void*)pll_reconfig->pll_config_data.data, pll_config_3x_4x_data, sizeof(pll_config_3x_4x_data));
|
||||
pll_reconfig->pll_config_status.update = 1;
|
||||
cm.pll_config = pll_config;
|
||||
}
|
||||
pll_reconfigure(cm.pll_config);
|
||||
|
||||
if (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X) {
|
||||
osd_x_size = (video_modes[cm.id].v_active > 700) ? 1 : 0;
|
||||
@ -748,8 +777,7 @@ int init_hw()
|
||||
|
||||
// Reload initial PLL config (needed after jtagm_reset_req if config has changed).
|
||||
// Note that test pattern gets restored only if pclk was active before jtagm_reset_req assertion.
|
||||
memcpy((void*)pll_reconfig->pll_config_data.data, pll_config_default_data, sizeof(pll_config_default_data));
|
||||
pll_reconfig->pll_config_status.update = 1;
|
||||
pll_reconfigure(PLL_CONFIG_VG);
|
||||
|
||||
//wait >500ms for SD card interface to be stable
|
||||
//over 200ms and LCD may be buggy?
|
||||
@ -893,10 +921,10 @@ int latency_test() {
|
||||
// Enable chip outputs
|
||||
void enable_outputs()
|
||||
{
|
||||
// program video mode
|
||||
program_mode();
|
||||
// enable TVP output
|
||||
tvp_enable_output();
|
||||
// program video mode
|
||||
program_mode();
|
||||
|
||||
// enable and unmute TX
|
||||
TX_enable(tc.tx_mode);
|
||||
|
@ -44,6 +44,8 @@
|
||||
// HDMI_TX definitions
|
||||
#define HDMITX_MODE_MASK 0x00040000
|
||||
|
||||
#define PLL_ACTIVECLK_MASK 0x00080000
|
||||
|
||||
#define TX_PIXELREP_DISABLE 0
|
||||
#define TX_PIXELREP_2X 1
|
||||
#define TX_PIXELREP_4X 3
|
||||
@ -84,6 +86,10 @@ typedef enum {
|
||||
TX_DVI = 2
|
||||
} tx_mode_t;
|
||||
|
||||
typedef struct {
|
||||
alt_u32 data[5];
|
||||
} pll_config_t;
|
||||
|
||||
//TODO: transform binary values into flags
|
||||
typedef struct {
|
||||
alt_u32 totlines;
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS">
|
||||
<!-- Format version 17.1 590 (Future versions may contain additional information.) -->
|
||||
<!-- 2019.10.10.00:51:29 -->
|
||||
<!-- 2019.10.12.20:50:18 -->
|
||||
<!-- A collection of modules and connections -->
|
||||
<parameter name="AUTO_GENERATION_ID">
|
||||
<type>java.lang.Integer</type>
|
||||
<value>1570657889</value>
|
||||
<value>1570902617</value>
|
||||
<derived>false</derived>
|
||||
<enabled>true</enabled>
|
||||
<visible>false</visible>
|
||||
|
Loading…
Reference in New Issue
Block a user