mirror of
https://github.com/marqs85/ossc.git
synced 2024-12-31 22:31:25 +00:00
make pll_reconfig more robust
This commit is contained in:
parent
8e7236dc00
commit
85c295c5e2
@ -26,7 +26,9 @@ typedef union {
|
|||||||
struct {
|
struct {
|
||||||
alt_u8 reset:1;
|
alt_u8 reset:1;
|
||||||
alt_u8 update: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;
|
alt_u8 busy:1;
|
||||||
} __attribute__((packed, __may_alias__));
|
} __attribute__((packed, __may_alias__));
|
||||||
alt_u32 data;
|
alt_u32 data;
|
||||||
|
@ -56,10 +56,12 @@ reg [1:0] state;
|
|||||||
reg scan_shift;
|
reg scan_shift;
|
||||||
reg scandone_prev;
|
reg scandone_prev;
|
||||||
reg configupdate_pre;
|
reg configupdate_pre;
|
||||||
reg [7:0] ctr;
|
reg [7:0] shift_ctr;
|
||||||
|
|
||||||
wire pll_reset = pll_config_status[0];
|
wire pll_reset = pll_config_status[0];
|
||||||
wire start_update = pll_config_status[1];
|
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];
|
wire config_busy = pll_config_status[31];
|
||||||
|
|
||||||
assign areset = pll_reset | areset_strobe;
|
assign areset = pll_reset | areset_strobe;
|
||||||
@ -141,7 +143,7 @@ begin
|
|||||||
if (start_update) begin
|
if (start_update) begin
|
||||||
pll_config_status[31] <= 1'b1;
|
pll_config_status[31] <= 1'b1;
|
||||||
scanclkena <= 1'b1;
|
scanclkena <= 1'b1;
|
||||||
ctr <= PLL_CONFIG_DATA_BITS;
|
shift_ctr <= PLL_CONFIG_DATA_BITS;
|
||||||
state <= STATE_SHIFT;
|
state <= STATE_SHIFT;
|
||||||
end else begin
|
end else begin
|
||||||
pll_config_status[31] <= 1'b0;
|
pll_config_status[31] <= 1'b0;
|
||||||
@ -150,22 +152,23 @@ begin
|
|||||||
STATE_SHIFT:
|
STATE_SHIFT:
|
||||||
begin
|
begin
|
||||||
scan_shift <= 1'b1;
|
scan_shift <= 1'b1;
|
||||||
if (ctr > 0) begin
|
if (shift_ctr > 0) begin
|
||||||
ctr <= ctr - 1'b1;
|
shift_ctr <= shift_ctr - 1'b1;
|
||||||
end else begin
|
end else begin
|
||||||
scan_shift <= 1'b0;
|
scan_shift <= 1'b0;
|
||||||
scanclkena <= 1'b0;
|
scanclkena <= 1'b0;
|
||||||
configupdate_pre <= 1'b1;
|
configupdate_pre <= 1'b1;
|
||||||
ctr <= 8'hff;
|
|
||||||
state <= STATE_WAITRESP;
|
state <= STATE_WAITRESP;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STATE_WAITRESP:
|
STATE_WAITRESP:
|
||||||
begin
|
begin
|
||||||
configupdate_pre <= 1'b0;
|
configupdate_pre <= 1'b0;
|
||||||
ctr <= ctr - 1'b1;
|
if (pll_reset) begin
|
||||||
if (scandone_prev | (ctr == 8'h0)) begin
|
state <= STATE_IDLE;
|
||||||
|
end else if (scandone_prev) begin
|
||||||
areset_strobe <= 1'b1;
|
areset_strobe <= 1'b1;
|
||||||
|
pll_config_status[30:27] <= t_config_id;
|
||||||
state <= STATE_IDLE;
|
state <= STATE_IDLE;
|
||||||
end
|
end
|
||||||
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] xpos, xpos_sc, xpos_vg;
|
||||||
wire [10:0] ypos, ypos_sc, ypos_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)
|
// 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_sda_pad_io (SD_CMD),
|
||||||
.i2c_opencores_1_export_spi_miso_pad_i (SD_DAT[0]),
|
.i2c_opencores_1_export_spi_miso_pad_i (SD_DAT[0]),
|
||||||
.pio_0_sys_ctrl_out_export (sys_ctrl),
|
.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_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_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}),
|
.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_scanclkena (pll_scanclkena),
|
||||||
.pll_configupdate (pll_configupdate),
|
.pll_configupdate (pll_configupdate),
|
||||||
.pll_scandata (pll_scandata),
|
.pll_scandata (pll_scandata),
|
||||||
.pll_scandone (pll_scandone)
|
.pll_scandone (pll_scandone),
|
||||||
|
.pll_activeclock (pll_activeclock)
|
||||||
);
|
);
|
||||||
|
|
||||||
ir_rcv ir0 (
|
ir_rcv ir0 (
|
||||||
|
@ -118,7 +118,8 @@ module scanconverter (
|
|||||||
input pll_scanclkena,
|
input pll_scanclkena,
|
||||||
input pll_configupdate,
|
input pll_configupdate,
|
||||||
input pll_scandata,
|
input pll_scandata,
|
||||||
output pll_scandone
|
output pll_scandone,
|
||||||
|
output pll_activeclock
|
||||||
);
|
);
|
||||||
|
|
||||||
//clock-related signals and registers
|
//clock-related signals and registers
|
||||||
@ -126,7 +127,6 @@ wire pclk_act;
|
|||||||
wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_5x;
|
wire pclk_1x, pclk_2x, pclk_3x, pclk_4x, pclk_5x;
|
||||||
wire [1:0] pclk_mux_sel;
|
wire [1:0] pclk_mux_sel;
|
||||||
wire pll_lock;
|
wire pll_lock;
|
||||||
wire pll_activeclock;
|
|
||||||
reg pll_clkswitch;
|
reg pll_clkswitch;
|
||||||
|
|
||||||
//RGB signals®isters: 8 bits per component -> 16.7M colors
|
//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 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 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;
|
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];
|
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
|
// 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)
|
// 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()
|
// 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 pll_config_t pll_configs[] = { {{0x0d806000, 0x00402010, 0x08040220, 0x00004022, 0x00000000}}, // 1x, 1x (default)
|
||||||
const alt_u32 pll_config_2x_5x_data[] = {0x0dc06000, 0x00783c11, 0x070180e0, 0x0000180e, 0x00000000};
|
{{0x0dc06000, 0x00783c11, 0x070180e0, 0x0000180e, 0x00000000}}, // 2x, 5x
|
||||||
const alt_u32 pll_config_3x_4x_data[] = {0x0d806000, 0x00301804, 0x02014060, 0x00001406, 0x00000000};
|
{{0x0d806000, 0x00301804, 0x02014060, 0x00001406, 0x00000000}} }; // 3x, 4x
|
||||||
|
|
||||||
volatile sc_regs *sc = (volatile sc_regs*)SC_CONFIG_0_BASE;
|
volatile sc_regs *sc = (volatile sc_regs*)SC_CONFIG_0_BASE;
|
||||||
volatile osd_regs *osd = (volatile osd_regs*)OSD_GENERATOR_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);
|
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)
|
void set_lpf(alt_u8 lpf)
|
||||||
{
|
{
|
||||||
alt_u32 pclk;
|
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))
|
if ((tc.s400p_mode != cm.cc.s400p_mode) && (video_modes[cm.id].v_total == 449))
|
||||||
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
|
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) {
|
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);
|
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));
|
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
|
// Configure TVP7002 and scan converter logic based on the video mode
|
||||||
void program_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;
|
alt_u32 h_hz, v_hz_x100, h_synclen_px;
|
||||||
|
|
||||||
// Mark as stable (needed after sync up to avoid unnecessary mode switch)
|
// 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);
|
set_csc(cm.cc.ypbpr_cs);
|
||||||
cm.sample_sel = tvp_set_hpll_phase(video_modes[cm.id].sampler_phase, cm.sample_mult);
|
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) {
|
switch (cm.fpga_vmultmode) {
|
||||||
case FPGA_V_MULTMODE_2X:
|
case FPGA_V_MULTMODE_2X:
|
||||||
case FPGA_V_MULTMODE_5X:
|
case FPGA_V_MULTMODE_5X:
|
||||||
pll_config = PLL_CONFIG_2X_5X;
|
cm.pll_config = PLL_CONFIG_2X_5X;
|
||||||
break;
|
break;
|
||||||
case FPGA_V_MULTMODE_3X:
|
case FPGA_V_MULTMODE_3X:
|
||||||
case FPGA_V_MULTMODE_4X:
|
case FPGA_V_MULTMODE_4X:
|
||||||
pll_config = PLL_CONFIG_3X_4X;
|
cm.pll_config = PLL_CONFIG_3X_4X;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pll_config = cm.pll_config;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
pll_reconfigure(cm.pll_config);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X) {
|
if (cm.fpga_vmultmode == FPGA_V_MULTMODE_1X) {
|
||||||
osd_x_size = (video_modes[cm.id].v_active > 700) ? 1 : 0;
|
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).
|
// 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.
|
// 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_reconfigure(PLL_CONFIG_VG);
|
||||||
pll_reconfig->pll_config_status.update = 1;
|
|
||||||
|
|
||||||
//wait >500ms for SD card interface to be stable
|
//wait >500ms for SD card interface to be stable
|
||||||
//over 200ms and LCD may be buggy?
|
//over 200ms and LCD may be buggy?
|
||||||
@ -893,10 +921,10 @@ int latency_test() {
|
|||||||
// Enable chip outputs
|
// Enable chip outputs
|
||||||
void enable_outputs()
|
void enable_outputs()
|
||||||
{
|
{
|
||||||
// program video mode
|
|
||||||
program_mode();
|
|
||||||
// enable TVP output
|
// enable TVP output
|
||||||
tvp_enable_output();
|
tvp_enable_output();
|
||||||
|
// program video mode
|
||||||
|
program_mode();
|
||||||
|
|
||||||
// enable and unmute TX
|
// enable and unmute TX
|
||||||
TX_enable(tc.tx_mode);
|
TX_enable(tc.tx_mode);
|
||||||
|
@ -44,6 +44,8 @@
|
|||||||
// HDMI_TX definitions
|
// HDMI_TX definitions
|
||||||
#define HDMITX_MODE_MASK 0x00040000
|
#define HDMITX_MODE_MASK 0x00040000
|
||||||
|
|
||||||
|
#define PLL_ACTIVECLK_MASK 0x00080000
|
||||||
|
|
||||||
#define TX_PIXELREP_DISABLE 0
|
#define TX_PIXELREP_DISABLE 0
|
||||||
#define TX_PIXELREP_2X 1
|
#define TX_PIXELREP_2X 1
|
||||||
#define TX_PIXELREP_4X 3
|
#define TX_PIXELREP_4X 3
|
||||||
@ -84,6 +86,10 @@ typedef enum {
|
|||||||
TX_DVI = 2
|
TX_DVI = 2
|
||||||
} tx_mode_t;
|
} tx_mode_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
alt_u32 data[5];
|
||||||
|
} pll_config_t;
|
||||||
|
|
||||||
//TODO: transform binary values into flags
|
//TODO: transform binary values into flags
|
||||||
typedef struct {
|
typedef struct {
|
||||||
alt_u32 totlines;
|
alt_u32 totlines;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS">
|
<EnsembleReport name="sys" kind="sys" version="1.0" fabric="QSYS">
|
||||||
<!-- Format version 17.1 590 (Future versions may contain additional information.) -->
|
<!-- 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 -->
|
<!-- A collection of modules and connections -->
|
||||||
<parameter name="AUTO_GENERATION_ID">
|
<parameter name="AUTO_GENERATION_ID">
|
||||||
<type>java.lang.Integer</type>
|
<type>java.lang.Integer</type>
|
||||||
<value>1570657889</value>
|
<value>1570902617</value>
|
||||||
<derived>false</derived>
|
<derived>false</derived>
|
||||||
<enabled>true</enabled>
|
<enabled>true</enabled>
|
||||||
<visible>false</visible>
|
<visible>false</visible>
|
||||||
|
Loading…
Reference in New Issue
Block a user