summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSomebody <definesinsanity@gmail.com>2013-03-29 13:10:14 +0800
committerChih-Wei Huang <cwhuang@linux.org.tw>2013-07-17 10:28:58 +0800
commit152d07cb6d5901f53f333d19bf2cb83acf8747fa (patch)
tree71f2846b18f3608be079987d28f353c4bc650b3d
parentb19bbdbf98742f0428f6f4265b5e80d569608abd (diff)
downloadexternal_drm_gralloc-152d07cb6d5901f53f333d19bf2cb83acf8747fa.zip
external_drm_gralloc-152d07cb6d5901f53f333d19bf2cb83acf8747fa.tar.gz
external_drm_gralloc-152d07cb6d5901f53f333d19bf2cb83acf8747fa.tar.bz2
allow to force graphics mode
This patch adds in a system property "debug.drm.mode.force", which works *similarly* to "debug.drm.mode". XRESxYRES[@REFRESHRATE].
-rw-r--r--gralloc_drm_kms.c157
1 files changed, 137 insertions, 20 deletions
diff --git a/gralloc_drm_kms.c b/gralloc_drm_kms.c
index 547b70c..0909361 100644
--- a/gralloc_drm_kms.c
+++ b/gralloc_drm_kms.c
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <poll.h>
+#include <math.h>
#include "gralloc_drm.h"
#include "gralloc_drm_priv.h"
#include <hardware_legacy/uevent.h>
@@ -683,12 +684,104 @@ static void drm_kms_init_features(struct gralloc_drm_t *drm)
ALOGD("will use %s for fb posting", swap_mode);
}
+#define MARGIN_PERCENT 1.8 /* % of active vertical image*/
+#define CELL_GRAN 8.0 /* assumed character cell granularity*/
+#define MIN_PORCH 1 /* minimum front porch */
+#define V_SYNC_RQD 3 /* width of vsync in lines */
+#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */
+#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */
+#define M 600.0 /* blanking formula gradient */
+#define C 40.0 /* blanking formula offset */
+#define K 128.0 /* blanking formula scaling factor */
+#define J 20.0 /* blanking formula scaling factor */
+/* C' and M' are part of the Blanking Duty Cycle computation */
+#define C_PRIME (((C - J) * K / 256.0) + J)
+#define M_PRIME (K / 256.0 * M)
+
+static drmModeModeInfoPtr generate_mode(int h_pixels, int v_lines, float freq)
+{
+ float h_pixels_rnd;
+ float v_lines_rnd;
+ float v_field_rate_rqd;
+ float top_margin;
+ float bottom_margin;
+ float interlace;
+ float h_period_est;
+ float vsync_plus_bp;
+ float v_back_porch;
+ float total_v_lines;
+ float v_field_rate_est;
+ float h_period;
+ float v_field_rate;
+ float v_frame_rate;
+ float left_margin;
+ float right_margin;
+ float total_active_pixels;
+ float ideal_duty_cycle;
+ float h_blank;
+ float total_pixels;
+ float pixel_freq;
+ float h_freq;
+
+ float h_sync;
+ float h_front_porch;
+ float v_odd_front_porch_lines;
+ int interlaced = 0;
+ int margins = 0;
+
+ drmModeModeInfoPtr m = malloc(sizeof(drmModeModeInfo));
+
+ h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN;
+ v_lines_rnd = interlaced ? rint((float) v_lines) / 2.0 : rint((float) v_lines);
+ v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq);
+ top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
+ bottom_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0);
+ interlace = interlaced ? 0.5 : 0.0;
+ h_period_est = (((1.0 / v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP / 1000000.0)) / (v_lines_rnd + (2 * top_margin) + MIN_PORCH + interlace) * 1000000.0);
+ vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP / h_period_est);
+ v_back_porch = vsync_plus_bp - V_SYNC_RQD;
+ total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp + interlace + MIN_PORCH;
+ v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
+ h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
+ v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0;
+ v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate;
+ left_margin = margins ? rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : 0.0;
+ right_margin = margins ? rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : 0.0;
+ total_active_pixels = h_pixels_rnd + left_margin + right_margin;
+ ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
+ h_blank = rint(total_active_pixels * ideal_duty_cycle / (100.0 - ideal_duty_cycle) / (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN);
+ total_pixels = total_active_pixels + h_blank;
+ pixel_freq = total_pixels / h_period;
+ h_freq = 1000.0 / h_period;
+ h_sync = rint(H_SYNC_PERCENT / 100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
+ h_front_porch = (h_blank / 2.0) - h_sync;
+ v_odd_front_porch_lines = MIN_PORCH + interlace;
+
+ m->clock = ceil(pixel_freq) * 1000;
+ m->hdisplay = (int) (h_pixels_rnd);
+ m->hsync_start = (int) (h_pixels_rnd + h_front_porch);
+ m->hsync_end = (int) (h_pixels_rnd + h_front_porch + h_sync);
+ m->htotal = (int) (total_pixels);
+ m->hskew = 0;
+ m->vdisplay = (int) (v_lines_rnd);
+ m->vsync_start = (int) (v_lines_rnd + v_odd_front_porch_lines);
+ m->vsync_end = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD);
+ m->vtotal = (int) (total_v_lines);
+ m->vscan = 0;
+ m->vrefresh = freq;
+ m->flags = 10;
+ m->type = 64;
+
+ return (m);
+}
+
static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
{
char value[PROPERTY_VALUE_MAX];
drmModeModeInfoPtr mode;
int dist, i;
- int xres = 0, yres = 0;
+ int xres = 0, yres = 0, rate = 0;
+ int forcemode = 0;
if (property_get("debug.drm.mode", value, NULL)) {
char *p = value, *end;
@@ -704,31 +797,50 @@ static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
ALOGI("will find the closest match for %dx%d@%d",
xres, yres, *bpp);
}
- }
- else {
+ } else if (property_get("debug.drm.mode.force", value, NULL)) {
+ char *p = value, *end;
+ *bpp = 0;
+
+ /* parse <xres>x<yres>[@<refreshrate>] */
+ if (sscanf(value, "%dx%d@%d", &xres, &yres, &rate) != 3) {
+ rate = 60;
+ if (sscanf(value, "%dx%d", &xres, &yres) != 2)
+ xres = yres = 0;
+ }
+
+ if (xres && yres && rate) {
+ ALOGI("will use %dx%d@%dHz", xres, yres, rate);
+ forcemode = 1;
+ }
+ } else {
*bpp = 0;
}
- mode = NULL;
dist = INT_MAX;
- for (i = 0; i < connector->count_modes; i++) {
- drmModeModeInfoPtr m = &connector->modes[i];
- int tmp;
- if (xres && yres) {
- tmp = (m->hdisplay - xres) * (m->hdisplay - xres) +
- (m->vdisplay - yres) * (m->vdisplay - yres);
- }
- else {
- /* use the first preferred mode */
- tmp = (m->type & DRM_MODE_TYPE_PREFERRED) ? 0 : dist;
- }
+ if (forcemode)
+ mode = generate_mode(xres, yres, rate);
+ else {
+ mode = NULL;
+ for (i = 0; i < connector->count_modes; i++) {
+ drmModeModeInfoPtr m = &connector->modes[i];
+ int tmp;
+
+ if (xres && yres) {
+ tmp = (m->hdisplay - xres) * (m->hdisplay - xres) +
+ (m->vdisplay - yres) * (m->vdisplay - yres);
+ }
+ else {
+ /* use the first preferred mode */
+ tmp = (m->type & DRM_MODE_TYPE_PREFERRED) ? 0 : dist;
+ }
- if (tmp < dist) {
- mode = m;
- dist = tmp;
- if (!dist)
- break;
+ if (tmp < dist) {
+ mode = m;
+ dist = tmp;
+ if (!dist)
+ break;
+ }
}
}
@@ -736,6 +848,11 @@ static drmModeModeInfoPtr find_mode(drmModeConnectorPtr connector, int *bpp)
if (!mode)
mode = &connector->modes[0];
+ ALOGI("Established mode:");
+ ALOGI("clock: %d, hdisplay: %d, hsync_start: %d, hsync_end: %d, htotal: %d, hskew: %d", mode->clock, mode->hdisplay, mode->hsync_start, mode->hsync_end, mode->htotal, mode->hskew);
+ ALOGI("vdisplay: %d, vsync_start: %d, vsync_end: %d, vtotal: %d, vscan: %d, vrefresh: %d", mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal, mode->vscan, mode->vrefresh);
+ ALOGI("flags: %d, type: %d, name %s", mode->flags, mode->type, mode->name);
+
*bpp /= 8;
return mode;