Support linux FB over VGA/Direct Video.
This commit is contained in:
114
video.cpp
114
video.cpp
@@ -42,6 +42,11 @@
|
||||
#define FB_FMT_RxB 0b10000
|
||||
#define FB_EN 0x8000
|
||||
|
||||
#define FB_DV_LBRD 3
|
||||
#define FB_DV_RBRD 6
|
||||
#define FB_DV_UBRD 2
|
||||
#define FB_DV_BBRD 2
|
||||
|
||||
|
||||
static volatile uint32_t *fb_base = 0;
|
||||
static int fb_enabled = 0;
|
||||
@@ -77,6 +82,14 @@ vmode_t vmodes[] =
|
||||
};
|
||||
#define VMODES_NUM (sizeof(vmodes) / sizeof(vmodes[0]))
|
||||
|
||||
vmode_t tvmodes[] =
|
||||
{
|
||||
{{ 640, 16, 96, 48, 240, 4, 4, 14 }, 12.587 }, //NTSC 15K
|
||||
{{ 640, 16, 96, 48, 480, 8, 4, 33 }, 25.175 }, //NTSC 31K
|
||||
{{ 640, 16, 96, 48, 288, 6, 4, 14 }, 12.587 }, //PAL 15K
|
||||
{{ 640, 16, 96, 48, 576, 2, 4, 42 }, 25.175 }, //PAL 31K
|
||||
};
|
||||
|
||||
struct vmode_custom_t
|
||||
{
|
||||
uint32_t item[32];
|
||||
@@ -404,19 +417,31 @@ static void set_video(vmode_custom_t *v, double Fpix)
|
||||
loadScalerCfg();
|
||||
setScaler();
|
||||
|
||||
v_cur = *v;
|
||||
|
||||
vmode_custom_t v_fix = v_cur;
|
||||
if (cfg.direct_video)
|
||||
{
|
||||
v_fix.item[2] = FB_DV_RBRD;
|
||||
v_fix.item[4] = FB_DV_LBRD;
|
||||
v_fix.item[1] += v_cur.item[2] - v_fix.item[2];
|
||||
v_fix.item[1] += v_cur.item[4] - v_fix.item[4];
|
||||
|
||||
v_fix.item[6] = FB_DV_BBRD;
|
||||
v_fix.item[8] = FB_DV_UBRD;;
|
||||
v_fix.item[5] += v_cur.item[6] - v_fix.item[6];
|
||||
v_fix.item[5] += v_cur.item[8] - v_fix.item[8];
|
||||
}
|
||||
|
||||
printf("Send HDMI parameters:\n");
|
||||
spi_uio_cmd_cont(UIO_SET_VIDEO);
|
||||
printf("video: ");
|
||||
for (int i = 1; i <= 8; i++)
|
||||
{
|
||||
v_cur.item[i] = v->item[i];
|
||||
spi_w(v_cur.item[i]);
|
||||
printf("%d, ", v_cur.item[i]);
|
||||
spi_w(v_fix.item[i]);
|
||||
printf("%d(%d), ", v_cur.item[i], v_fix.item[i]);
|
||||
}
|
||||
|
||||
for (int i = 9; i < 21; i++) v_cur.item[i] = v->item[i];
|
||||
v_cur.Fpix = v->Fpix;
|
||||
|
||||
if(Fpix) setPLL(Fpix, &v_cur);
|
||||
|
||||
printf("\nPLL: ");
|
||||
@@ -548,9 +573,26 @@ void video_mode_load()
|
||||
printf("Disabling vsync_adjust because of enabled direct video.\n");
|
||||
cfg.vsync_adjust = 0;
|
||||
}
|
||||
vmode_def = store_custom_video_mode(cfg.video_conf, &v_def);
|
||||
vmode_pal = store_custom_video_mode(cfg.video_conf_pal, &v_pal);
|
||||
vmode_ntsc = store_custom_video_mode(cfg.video_conf_ntsc, &v_ntsc);
|
||||
|
||||
if (cfg.direct_video)
|
||||
{
|
||||
int mode = cfg.menu_pal ? 2 : 0;
|
||||
if (cfg.forced_scandoubler) mode++;
|
||||
|
||||
v_def.item[0] = mode;
|
||||
for (int i = 0; i < 8; i++) v_def.item[i + 1] = tvmodes[mode].vpar[i];
|
||||
setPLL(tvmodes[mode].Fpix, &v_def);
|
||||
|
||||
vmode_def = 1;
|
||||
vmode_pal = 0;
|
||||
vmode_ntsc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vmode_def = store_custom_video_mode(cfg.video_conf, &v_def);
|
||||
vmode_pal = store_custom_video_mode(cfg.video_conf_pal, &v_pal);
|
||||
vmode_ntsc = store_custom_video_mode(cfg.video_conf_ntsc, &v_ntsc);
|
||||
}
|
||||
set_video(&v_def, 0);
|
||||
}
|
||||
|
||||
@@ -708,6 +750,7 @@ void video_fb_enable(int enable, int n)
|
||||
{
|
||||
if (fb_base)
|
||||
{
|
||||
if (cfg.direct_video) set_vga_fb(enable);
|
||||
int res = spi_uio_cmd_cont(UIO_SET_FBUF);
|
||||
if (res)
|
||||
{
|
||||
@@ -722,16 +765,23 @@ void video_fb_enable(int enable, int n)
|
||||
uint32_t fb_addr = FB_ADDR + (FB_SIZE * 4 * n) + (n ? 0 : 4096);
|
||||
fb_num = n;
|
||||
|
||||
int xoff = 0, yoff = 0;
|
||||
if (cfg.direct_video)
|
||||
{
|
||||
xoff = v_cur.item[4] - FB_DV_LBRD;
|
||||
yoff = v_cur.item[8] - FB_DV_UBRD;
|
||||
}
|
||||
|
||||
printf("Switch to HPS frame buffer\n");
|
||||
spi_w((uint16_t)(FB_EN | FB_FMT_RxB | FB_FMT_8888)); // format, enable flag
|
||||
spi_w((uint16_t)fb_addr); // base address low word
|
||||
spi_w(fb_addr >> 16); // base address high word
|
||||
spi_w(fb_width); // frame width
|
||||
spi_w(fb_height); // frame height
|
||||
spi_w(0); // scaled left
|
||||
spi_w(v_cur.item[1] - 1); // scaled right
|
||||
spi_w(0); // scaled top
|
||||
spi_w(v_cur.item[5] - 1); // scaled bottom
|
||||
spi_w(xoff); // scaled left
|
||||
spi_w(xoff + v_cur.item[1] - 1); // scaled right
|
||||
spi_w(yoff); // scaled top
|
||||
spi_w(yoff + v_cur.item[5] - 1); // scaled bottom
|
||||
|
||||
printf("HPS frame buffer: %dx%d, stride = %d bytes\n", fb_width, fb_height, fb_stride);
|
||||
if (!fb_num)
|
||||
@@ -1301,13 +1351,24 @@ void video_cmd(char *cmd)
|
||||
if (width < 120 || width > (int)v_cur.item[1]) width = v_cur.item[1];
|
||||
if (height < 120 || height > (int)v_cur.item[5]) height = v_cur.item[5];
|
||||
|
||||
div = 1;
|
||||
while ((width*(div + 1)) <= (int)v_cur.item[1] && (height*(div + 1)) <= (int)v_cur.item[5]) div++;
|
||||
int divx = 1;
|
||||
int divy = 1;
|
||||
if (cfg.direct_video && (v_cur.item[5] < 300))
|
||||
{
|
||||
// TV 240P/288P
|
||||
while ((width*(divx + 1)) <= (int)v_cur.item[1]) divx++;
|
||||
while ((height*(divy + 1)) <= (int)v_cur.item[5]) divy++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((width*(divx + 1)) <= (int)v_cur.item[1] && (height*(divx + 1)) <= (int)v_cur.item[5]) divx++;
|
||||
divy = divx;
|
||||
}
|
||||
|
||||
hmin = (uint16_t)((v_cur.item[1] - (width * div)) / 2);
|
||||
vmin = (uint16_t)((v_cur.item[5] - (height * div)) / 2);
|
||||
hmax = hmin + (width * div) - 1;
|
||||
vmax = vmin + (height * div) - 1;
|
||||
hmin = (uint16_t)((v_cur.item[1] - (width * divx)) / 2);
|
||||
vmin = (uint16_t)((v_cur.item[5] - (height * divy)) / 2);
|
||||
hmax = hmin + (width * divx) - 1;
|
||||
vmax = vmin + (height * divy) - 1;
|
||||
accept = 1;
|
||||
}
|
||||
|
||||
@@ -1357,16 +1418,23 @@ void video_cmd(char *cmd)
|
||||
|
||||
uint32_t addr = FB_ADDR + 4096;
|
||||
|
||||
int xoff = 0, yoff = 0;
|
||||
if (cfg.direct_video)
|
||||
{
|
||||
xoff = v_cur.item[4] - FB_DV_LBRD;
|
||||
yoff = v_cur.item[8] - FB_DV_UBRD;
|
||||
}
|
||||
|
||||
spi_uio_cmd_cont(UIO_SET_FBUF);
|
||||
spi_w(FB_EN | sc_fmt); // format, enable flag
|
||||
spi_w((uint16_t)addr); // base address low word
|
||||
spi_w(addr >> 16); // base address high word
|
||||
spi_w(width); // frame width
|
||||
spi_w(height); // frame height
|
||||
spi_w(hmin); // scaled left
|
||||
spi_w(hmax); // scaled right
|
||||
spi_w(vmin); // scaled top
|
||||
spi_w(vmax); // scaled bottom
|
||||
spi_w(xoff + hmin); // scaled left
|
||||
spi_w(xoff + hmax); // scaled right
|
||||
spi_w(yoff + vmin); // scaled top
|
||||
spi_w(yoff + vmax); // scaled bottom
|
||||
DisableIO();
|
||||
|
||||
if (cmd[6] != '2')
|
||||
|
||||
Reference in New Issue
Block a user