mirror of
https://github.com/MiSTer-devel/Main_MiSTer.git
synced 2026-05-31 03:04:12 +00:00
* hdmi_cec * Improve HDMI CEC startup * hdmi_cec * Improve HDMI CEC startup * Use ADV7513 interrupt registers for CEC Set ADV7513 main 0xE1 to the CEC I2C map address, 0xE2 to 0x00 to power the CEC block, and 0xE3 |= 0x0E for CEC control setup. Keep HPD forced high through main 0xD6 = 0xC0 after the startup pulse, but clear main 0x94[7] so HPD does not drive the shared HDMI interrupt line. Clear main 0xA1[6] so the monitor-sense/video-active block stays powered; ADV7513 interrupt status registers 0x94-0x97 are only valid while that block is alive. Set main 0x95 = 0x07 to enable only CEC RX-ready interrupts, use main 0x97 to clear RX/TX interrupt latches, and clear 0x96/0x97 at init. Read CEC RX-ready from CEC map 0x49, keep CEC RX enabled with 0x4A = 0x08, release consumed RX slots through 0x4A, and remove fallback polling of RX length registers 0x25/0x37/0x48. Use main 0x97 bits for CEC TX done/retry/arbitration status, keep CEC TX disabled through 0x11 except while sending, and set the CEC clock divider 0x4E = 0x3D. Gate RX handling on fpga_get_hdmi_int() so normal CEC polling no longer performs DDC/CEC I2C reads unless the FPGA HDMI interrupt bit is asserted. Reply to CEC vendor/name discovery so displays can identify MiSTer after registration. --------- Co-authored-by: misteraddons <51079966+misteraddons@users.noreply.github.com>
130 lines
2.1 KiB
C++
130 lines
2.1 KiB
C++
#include "scheduler.h"
|
|
#include <stdio.h>
|
|
#include "libco.h"
|
|
#include "menu.h"
|
|
#include "user_io.h"
|
|
#include "input.h"
|
|
#include "frame_timer.h"
|
|
#include "fpga_io.h"
|
|
#include "osd.h"
|
|
#include "profiling.h"
|
|
#include "cfg.h"
|
|
#include "hardware.h"
|
|
#include "hdmi_cec.h"
|
|
|
|
static cothread_t co_scheduler = nullptr;
|
|
static cothread_t co_poll = nullptr;
|
|
static cothread_t co_ui = nullptr;
|
|
static cothread_t co_last = nullptr;
|
|
static unsigned long cec_retry = 0;
|
|
static bool cec_init_failed_logged = false;
|
|
static bool scheduler_ui_ran_once = false;
|
|
|
|
static void scheduler_wait_fpga_ready(void)
|
|
{
|
|
while (!is_fpga_ready(1))
|
|
{
|
|
fpga_wait_to_reset();
|
|
}
|
|
}
|
|
|
|
static void scheduler_co_poll(void)
|
|
{
|
|
for (;;)
|
|
{
|
|
scheduler_wait_fpga_ready();
|
|
|
|
{
|
|
SPIKE_SCOPE("co_poll", 1000);
|
|
user_io_poll();
|
|
frame_timer();
|
|
input_poll(0);
|
|
}
|
|
|
|
if (cfg.hdmi_cec)
|
|
{
|
|
if (scheduler_ui_ran_once && !cec_is_enabled() && CheckTimer(cec_retry))
|
|
{
|
|
if (!cec_init(true))
|
|
{
|
|
if (cfg.debug && !cec_init_failed_logged) printf("CEC: init failed\n");
|
|
cec_init_failed_logged = true;
|
|
cec_retry = GetTimer(3000);
|
|
}
|
|
else
|
|
{
|
|
cec_init_failed_logged = false;
|
|
cec_retry = 0;
|
|
}
|
|
}
|
|
|
|
if (cec_is_enabled()) cec_poll();
|
|
}
|
|
else
|
|
{
|
|
if (cec_is_enabled()) cec_deinit();
|
|
cec_retry = 0;
|
|
cec_init_failed_logged = false;
|
|
}
|
|
|
|
scheduler_yield();
|
|
}
|
|
}
|
|
|
|
static void scheduler_co_ui(void)
|
|
{
|
|
for (;;)
|
|
{
|
|
scheduler_ui_ran_once = true;
|
|
|
|
{
|
|
SPIKE_SCOPE("co_ui", 1000);
|
|
HandleUI();
|
|
OsdUpdate();
|
|
}
|
|
|
|
scheduler_yield();
|
|
}
|
|
}
|
|
|
|
static void scheduler_schedule(void)
|
|
{
|
|
if (co_last == co_poll)
|
|
{
|
|
co_last = co_ui;
|
|
co_switch(co_ui);
|
|
}
|
|
else
|
|
{
|
|
co_last = co_poll;
|
|
co_switch(co_poll);
|
|
}
|
|
}
|
|
|
|
void scheduler_init(void)
|
|
{
|
|
const unsigned int co_stack_size = 262144 * sizeof(void*);
|
|
|
|
co_poll = co_create(co_stack_size, scheduler_co_poll);
|
|
co_ui = co_create(co_stack_size, scheduler_co_ui);
|
|
}
|
|
|
|
void scheduler_run(void)
|
|
{
|
|
co_scheduler = co_active();
|
|
|
|
for (;;)
|
|
{
|
|
scheduler_schedule();
|
|
}
|
|
|
|
co_delete(co_ui);
|
|
co_delete(co_poll);
|
|
co_delete(co_scheduler);
|
|
}
|
|
|
|
void scheduler_yield(void)
|
|
{
|
|
co_switch(co_scheduler);
|
|
}
|