From 1fa198a4234e46641611ee563130b080e3f24320 Mon Sep 17 00:00:00 2001 From: David Banks Date: Sun, 11 Nov 2018 18:06:55 +0000 Subject: [PATCH] Pi Firmware: implemented h_width and v_height Change-Id: I15bd6f1ec62a645643275bee2bf6dbd5d54dc1dc --- src/cpld.h | 2 +- src/cpld_alternative.c | 13 ++++----- src/cpld_normal.c | 61 +++++++++++++++++++++++++++++------------- src/rgb_to_fb.S | 22 ++++++++++++--- src/rgb_to_hdmi.c | 45 +++++++++++-------------------- 5 files changed, 84 insertions(+), 59 deletions(-) diff --git a/src/cpld.h b/src/cpld.h index 1da1efc5..c61445f7 100644 --- a/src/cpld.h +++ b/src/cpld.h @@ -27,7 +27,7 @@ typedef struct { int (*get_value)(int num); void (*set_value)(int num, int value); // Support for filling in framebuffer params - int (*get_fb_params)(capture_info_t *capinfo); + void (*get_fb_params)(capture_info_t *capinfo); // Support for info page void (*show_cal_summary)(int line); void (*show_cal_details)(int line); diff --git a/src/cpld_alternative.c b/src/cpld_alternative.c index e0d1f993..d1e18ae9 100644 --- a/src/cpld_alternative.c +++ b/src/cpld_alternative.c @@ -307,12 +307,13 @@ static void cpld_set_mode(int mode) { write_config(config); } -static int cpld_get_fb_params(capture_info_t *capinfo) { - capinfo->h_offset = 0; - capinfo->v_offset = 21; - capinfo->width = mode7 ? 504 : 672; - capinfo->height = 540; - return 0; +static void cpld_get_fb_params(capture_info_t *capinfo) { + capinfo->h_offset = 0; + capinfo->v_offset = 21; + capinfo->chars_per_line = mode7 ? 63 : 83; + capinfo->nlines = 270; + capinfo->width = mode7 ? 504 : 672; + capinfo->height = 540; } static param_t *cpld_get_params() { diff --git a/src/cpld_normal.c b/src/cpld_normal.c index a4e9b5b6..5d5d2d1c 100644 --- a/src/cpld_normal.c +++ b/src/cpld_normal.c @@ -16,10 +16,12 @@ typedef struct { int sp_offset[NUM_OFFSETS]; int half_px_delay; // 0 = off, 1 = on, all modes int full_px_delay; // 0..15, mode 7 only - int h_offset; // horizontal offset (in psync clocks) - int v_offset; // vertical offset (in lines) - int fb_width; // framebuffer width in pixels - int fb_height; // framebuffer height in pixels + int h_offset; // horizontal offset (in psync clocks) + int v_offset; // vertical offset (in lines) + int h_width; // active horizontal width (in 8-bit characters) + int v_height; // active vertical height (in lines) + int fb_width; // framebuffer width in pixels + int fb_height; // framebuffer height in pixels } config_t; // Current calibration state for mode 0..6 @@ -74,6 +76,8 @@ enum { HALF, H_OFFSET, V_OFFSET, + H_WIDTH, + V_HEIGHT, FB_WIDTH, FB_HEIGHT, DELAY @@ -90,8 +94,10 @@ static param_t default_params[] = { { "Half", 0, 1 }, { "H offset", 0, 59 }, { "V offset", 0, 39 }, + { "H width", 50, 99 }, + { "V height", 150, 300 }, { "FB width", 400, 800 }, - { "FB height", 540, 540 }, + { "FB height", 480, 600 }, { "Delay", 0, 15 }, { NULL, 0, 0 }, }; @@ -107,8 +113,10 @@ static param_t mode7_params[] = { { "Half", 0, 1 }, { "H offset", 0, 39 }, { "V offset", 0, 39 }, + { "H width", 50, 99 }, + { "V height", 150, 300 }, { "FB width", 400, 800 }, - { "FB height", 540, 540 }, + { "FB height", 480, 600 }, { "Delay", 0, 15 }, { NULL, 0, 0 }, }; @@ -207,12 +215,20 @@ static void log_sp(config_t *config) { static void cpld_init(int version) { cpld_version = version; // Setup default frame buffer params - mode7_config.h_offset = 24; - mode7_config.v_offset = 21; + // + // Nominal width should be 640x512 or 480x504, but making this a bit larger deals with two problems: + // 1. Slight differences in the horizontal placement in the different screen modes + // 2. Slight differences in the vertical placement due to *TV settings + mode7_config.h_offset = 24; + mode7_config.v_offset = 21; + mode7_config.h_width = 63; + mode7_config.v_height = 270; mode7_config.fb_width = 504; mode7_config.fb_height = 540; - default_config.h_offset = 32; - default_config.v_offset = 21; + default_config.h_offset = 32; + default_config.v_offset = 21; + default_config.h_width = 83; + default_config.v_height = 270; default_config.fb_width = 672; default_config.fb_height = 540; // Version 2 CPLD supports the delay parameter, and starts sampling earlier @@ -402,14 +418,13 @@ static void cpld_set_mode(int mode) { write_config(config); } -static int cpld_get_fb_params(capture_info_t *capinfo) { - int old_fb_width = capinfo->width; - int old_fb_height = capinfo->height; - capinfo->h_offset = config->h_offset; - capinfo->v_offset = config->v_offset; - capinfo->width = config->fb_width; - capinfo->height = config->fb_height; - return (old_fb_width != config->fb_width) || (old_fb_height != config->fb_height); +static void cpld_get_fb_params(capture_info_t *capinfo) { + capinfo->h_offset = config->h_offset; + capinfo->v_offset = config->v_offset; + capinfo->chars_per_line = config->h_width; + capinfo->nlines = config->v_height; + capinfo->width = config->fb_width; + capinfo->height = config->fb_height; } static param_t *cpld_get_params() { @@ -442,6 +457,10 @@ static int cpld_get_value(int num) { return config->h_offset; case V_OFFSET: return config->v_offset; + case H_WIDTH: + return config->h_width; + case V_HEIGHT: + return config->v_height; case FB_WIDTH: return config->fb_width; case FB_HEIGHT: @@ -489,6 +508,12 @@ static void cpld_set_value(int num, int value) { case V_OFFSET: config->v_offset = value; break; + case H_WIDTH: + config->h_width = value; + break; + case V_HEIGHT: + config->v_height = value; + break; case FB_WIDTH: config->fb_width = value; break; diff --git a/src/rgb_to_fb.S b/src/rgb_to_fb.S index 2ef7ec08..9a3b44b9 100644 --- a/src/rgb_to_fb.S +++ b/src/rgb_to_fb.S @@ -642,9 +642,23 @@ rgb_to_fb: ldr r2, [r0, #O_FB_BASE] str r2, param_framebuffer0 + // Sanity check chars_per_line <= fb_width / 8 + ldr r2, param_chars_per_line + ldr r3, param_fb_width + lsr r3, r3, #3 + cmp r2, r3 + strgt r3, param_chars_per_line + + // Sanity check nlines <= fb_height / 2 + ldr r2, param_nlines + ldr r3, param_fb_height + lsr r3, r3, #1 + cmp r2, r3 + strgt r3, param_nlines #ifdef MULTI_BUFFER - // Calculate the base address of each of the 4 frame buffers + // Calculate the base address of each of the 4 frame buffers + ldr r2, param_framebuffer0 ldr r10, param_fb_height ldr r11, param_fb_pitch mul r10, r10, r11 @@ -667,13 +681,13 @@ skip_swap: ldr r4, =GPLEV0 // Setup r3 with the flags/options parameter (as per before) - mov r3, r1 + mov r3, r1 // Setup r2 with the framebuffer pitch (as per before) - ldr r2, param_fb_pitch + ldr r2, param_fb_pitch // Setup r2 with the number of active characters per line (as per before) - ldr r1, param_chars_per_line + ldr r1, param_chars_per_line tst r3, #BIT_CLEAR blne clear_screen diff --git a/src/rgb_to_hdmi.c b/src/rgb_to_hdmi.c index e2b3e25e..f7e6405e 100644 --- a/src/rgb_to_hdmi.c +++ b/src/rgb_to_hdmi.c @@ -962,37 +962,13 @@ void rgb_to_hdmi_main() { int result; int last_mode7; - int size_changed; + int fb_size_changed; + int active_size_changed; + + capture_info_t last_capinfo; capinfo = &default_capinfo; - // Define the size of the Pi Framebuffer - // - // Nominal width should be 640x512 or 480x504, but making this a bit larger deals with two problems: - // 1. Slight differences in the horizontal placement in the different screen modes - // 2. Slight differences in the vertical placement due to *TV settings - - // Setup the default capture info values - default_capinfo.fb = NULL; // filled in by init_framebuffer - default_capinfo.pitch = 0; // filled in by init_framebuffer - default_capinfo.width = 672; - default_capinfo.height = 540; - default_capinfo.chars_per_line = 83; - default_capinfo.nlines = 270; - default_capinfo.h_offset = 0; // for compatibility with CPLDv1 - default_capinfo.v_offset = 21; - - - // Setup the mode7 capture info values - mode7_capinfo.fb = NULL; // filled in by init_framebuffer - mode7_capinfo.pitch = 0; // filled in by init_framebuffer - mode7_capinfo.width = 504; - mode7_capinfo.height = 540; - mode7_capinfo.chars_per_line = 63; - mode7_capinfo.nlines = 270; - mode7_capinfo.h_offset = 0; // for compatibility with CPLDv1 - mode7_capinfo.v_offset = 21; - // Initialize the cpld after the gpclk generator has been started cpld_init(); @@ -1068,12 +1044,21 @@ void rgb_to_hdmi_main() { } // Possibly the size or offset has been adjusted, so update these - size_changed = cpld->get_fb_params(capinfo); + + memcpy(&last_capinfo, capinfo, sizeof last_capinfo); + cpld->get_fb_params(capinfo); + + fb_size_changed = (capinfo->width != last_capinfo.width) || (capinfo->height != last_capinfo.height); + active_size_changed = (capinfo->chars_per_line != last_capinfo.chars_per_line) || (capinfo->nlines != last_capinfo.nlines); last_mode7 = mode7; mode7 = result & BIT_MODE7; - } while (mode7 == last_mode7 && !size_changed); + if (active_size_changed) { + clear = BIT_CLEAR; + } + + } while (mode7 == last_mode7 && !fb_size_changed); osd_clear(); }