aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_edid.c119
-rw-r--r--drivers/gpu/drm/drm_modes.c81
-rw-r--r--include/drm/drm_crtc.h4
3 files changed, 150 insertions, 54 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 6e999bd03935..3924a7bf271a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -64,7 +64,8 @@
64 64
65#define LEVEL_DMT 0 65#define LEVEL_DMT 0
66#define LEVEL_GTF 1 66#define LEVEL_GTF 1
67#define LEVEL_CVT 2 67#define LEVEL_GTF2 2
68#define LEVEL_CVT 3
68 69
69static struct edid_quirk { 70static struct edid_quirk {
70 char *vendor; 71 char *vendor;
@@ -713,6 +714,71 @@ drm_monitor_supports_rb(struct edid *edid)
713 return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0); 714 return ((edid->input & DRM_EDID_INPUT_DIGITAL) != 0);
714} 715}
715 716
717static void
718find_gtf2(struct detailed_timing *t, void *data)
719{
720 u8 *r = (u8 *)t;
721 if (r[3] == EDID_DETAIL_MONITOR_RANGE && r[10] == 0x02)
722 *(u8 **)data = r;
723}
724
725/* Secondary GTF curve kicks in above some break frequency */
726static int
727drm_gtf2_hbreak(struct edid *edid)
728{
729 u8 *r = NULL;
730 drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
731 return r ? (r[12] * 2) : 0;
732}
733
734static int
735drm_gtf2_2c(struct edid *edid)
736{
737 u8 *r = NULL;
738 drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
739 return r ? r[13] : 0;
740}
741
742static int
743drm_gtf2_m(struct edid *edid)
744{
745 u8 *r = NULL;
746 drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
747 return r ? (r[15] << 8) + r[14] : 0;
748}
749
750static int
751drm_gtf2_k(struct edid *edid)
752{
753 u8 *r = NULL;
754 drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
755 return r ? r[16] : 0;
756}
757
758static int
759drm_gtf2_2j(struct edid *edid)
760{
761 u8 *r = NULL;
762 drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
763 return r ? r[17] : 0;
764}
765
766/**
767 * standard_timing_level - get std. timing level(CVT/GTF/DMT)
768 * @edid: EDID block to scan
769 */
770static int standard_timing_level(struct edid *edid)
771{
772 if (edid->revision >= 2) {
773 if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
774 return LEVEL_CVT;
775 if (drm_gtf2_hbreak(edid))
776 return LEVEL_GTF2;
777 return LEVEL_GTF;
778 }
779 return LEVEL_DMT;
780}
781
716/* 782/*
717 * 0 is reserved. The spec says 0x01 fill for unused timings. Some old 783 * 0 is reserved. The spec says 0x01 fill for unused timings. Some old
718 * monitors fill with ascii space (0x20) instead. 784 * monitors fill with ascii space (0x20) instead.
@@ -734,8 +800,8 @@ bad_std_timing(u8 a, u8 b)
734 * and convert them into a real mode using CVT/GTF/DMT. 800 * and convert them into a real mode using CVT/GTF/DMT.
735 */ 801 */
736static struct drm_display_mode * 802static struct drm_display_mode *
737drm_mode_std(struct drm_connector *connector, struct std_timing *t, 803drm_mode_std(struct drm_connector *connector, struct edid *edid,
738 int revision, int timing_level) 804 struct std_timing *t, int revision)
739{ 805{
740 struct drm_device *dev = connector->dev; 806 struct drm_device *dev = connector->dev;
741 struct drm_display_mode *m, *mode = NULL; 807 struct drm_display_mode *m, *mode = NULL;
@@ -745,6 +811,7 @@ drm_mode_std(struct drm_connector *connector, struct std_timing *t,
745 >> EDID_TIMING_ASPECT_SHIFT; 811 >> EDID_TIMING_ASPECT_SHIFT;
746 unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK) 812 unsigned vfreq = (t->vfreq_aspect & EDID_TIMING_VFREQ_MASK)
747 >> EDID_TIMING_VFREQ_SHIFT; 813 >> EDID_TIMING_VFREQ_SHIFT;
814 int timing_level = standard_timing_level(edid);
748 815
749 if (bad_std_timing(t->hsize, t->vfreq_aspect)) 816 if (bad_std_timing(t->hsize, t->vfreq_aspect))
750 return NULL; 817 return NULL;
@@ -806,6 +873,23 @@ drm_mode_std(struct drm_connector *connector, struct std_timing *t,
806 case LEVEL_GTF: 873 case LEVEL_GTF:
807 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0); 874 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
808 break; 875 break;
876 case LEVEL_GTF2:
877 /*
878 * This is potentially wrong if there's ever a monitor with
879 * more than one ranges section, each claiming a different
880 * secondary GTF curve. Please don't do that.
881 */
882 mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
883 if (drm_mode_hsync(mode) > drm_gtf2_hbreak(edid)) {
884 kfree(mode);
885 mode = drm_gtf_mode_complex(dev, hsize, vsize,
886 vrefresh_rate, 0, 0,
887 drm_gtf2_m(edid),
888 drm_gtf2_2c(edid),
889 drm_gtf2_k(edid),
890 drm_gtf2_2j(edid));
891 }
892 break;
809 case LEVEL_CVT: 893 case LEVEL_CVT:
810 mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0, 894 mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
811 false); 895 false);
@@ -1042,19 +1126,6 @@ static int add_established_modes(struct drm_connector *connector, struct edid *e
1042 1126
1043 return modes; 1127 return modes;
1044} 1128}
1045/**
1046 * stanard_timing_level - get std. timing level(CVT/GTF/DMT)
1047 * @edid: EDID block to scan
1048 */
1049static int standard_timing_level(struct edid *edid)
1050{
1051 if (edid->revision >= 2) {
1052 if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
1053 return LEVEL_CVT;
1054 return LEVEL_GTF;
1055 }
1056 return LEVEL_DMT;
1057}
1058 1129
1059/** 1130/**
1060 * add_standard_modes - get std. modes from EDID and add them 1131 * add_standard_modes - get std. modes from EDID and add them
@@ -1066,15 +1137,13 @@ static int standard_timing_level(struct edid *edid)
1066static int add_standard_modes(struct drm_connector *connector, struct edid *edid) 1137static int add_standard_modes(struct drm_connector *connector, struct edid *edid)
1067{ 1138{
1068 int i, modes = 0; 1139 int i, modes = 0;
1069 int timing_level;
1070
1071 timing_level = standard_timing_level(edid);
1072 1140
1073 for (i = 0; i < EDID_STD_TIMINGS; i++) { 1141 for (i = 0; i < EDID_STD_TIMINGS; i++) {
1074 struct drm_display_mode *newmode; 1142 struct drm_display_mode *newmode;
1075 1143
1076 newmode = drm_mode_std(connector, &edid->standard_timings[i], 1144 newmode = drm_mode_std(connector, edid,
1077 edid->revision, timing_level); 1145 &edid->standard_timings[i],
1146 edid->revision);
1078 if (newmode) { 1147 if (newmode) {
1079 drm_mode_probed_add(connector, newmode); 1148 drm_mode_probed_add(connector, newmode);
1080 modes++; 1149 modes++;
@@ -1140,9 +1209,6 @@ range_pixel_clock(struct edid *edid, u8 *t)
1140 return t[9] * 10000 + 5001; 1209 return t[9] * 10000 + 5001;
1141} 1210}
1142 1211
1143/*
1144 * XXX fix this for GTF secondary curve formula
1145 */
1146static bool 1212static bool
1147mode_in_range(struct drm_display_mode *mode, struct edid *edid, 1213mode_in_range(struct drm_display_mode *mode, struct edid *edid,
1148 struct detailed_timing *timing) 1214 struct detailed_timing *timing)
@@ -1339,7 +1405,6 @@ static int add_detailed_modes(struct drm_connector *connector,
1339{ 1405{
1340 int i, modes = 0; 1406 int i, modes = 0;
1341 struct detailed_non_pixel *data = &timing->data.other_data; 1407 struct detailed_non_pixel *data = &timing->data.other_data;
1342 int timing_level = standard_timing_level(edid);
1343 int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); 1408 int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF);
1344 struct drm_display_mode *newmode; 1409 struct drm_display_mode *newmode;
1345 struct drm_device *dev = connector->dev; 1410 struct drm_device *dev = connector->dev;
@@ -1370,8 +1435,8 @@ static int add_detailed_modes(struct drm_connector *connector,
1370 struct drm_display_mode *newmode; 1435 struct drm_display_mode *newmode;
1371 1436
1372 std = &data->data.timings[i]; 1437 std = &data->data.timings[i];
1373 newmode = drm_mode_std(connector, std, edid->revision, 1438 newmode = drm_mode_std(connector, edid, std,
1374 timing_level); 1439 edid->revision);
1375 if (newmode) { 1440 if (newmode) {
1376 drm_mode_probed_add(connector, newmode); 1441 drm_mode_probed_add(connector, newmode);
1377 modes++; 1442 modes++;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 76d63394c776..d460b6c472d4 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -276,35 +276,29 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
276EXPORT_SYMBOL(drm_cvt_mode); 276EXPORT_SYMBOL(drm_cvt_mode);
277 277
278/** 278/**
279 * drm_gtf_mode - create the modeline based on GTF algorithm 279 * drm_gtf_mode_complex - create the modeline based on full GTF algorithm
280 * 280 *
281 * @dev :drm device 281 * @dev :drm device
282 * @hdisplay :hdisplay size 282 * @hdisplay :hdisplay size
283 * @vdisplay :vdisplay size 283 * @vdisplay :vdisplay size
284 * @vrefresh :vrefresh rate. 284 * @vrefresh :vrefresh rate.
285 * @interlaced :whether the interlace is supported 285 * @interlaced :whether the interlace is supported
286 * @margins :whether the margin is supported 286 * @margins :desired margin size
287 * @GTF_[MCKJ] :extended GTF formula parameters
287 * 288 *
288 * LOCKING. 289 * LOCKING.
289 * none. 290 * none.
290 * 291 *
291 * return the modeline based on GTF algorithm 292 * return the modeline based on full GTF algorithm.
292 *
293 * This function is to create the modeline based on the GTF algorithm.
294 * Generalized Timing Formula is derived from:
295 * GTF Spreadsheet by Andy Morrish (1/5/97)
296 * available at http://www.vesa.org
297 * 293 *
298 * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c. 294 * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
299 * What I have done is to translate it by using integer calculation. 295 * in here multiplied by two. For a C of 40, pass in 80.
300 * I also refer to the function of fb_get_mode in the file of
301 * drivers/video/fbmon.c
302 */ 296 */
303struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, 297struct drm_display_mode *
304 int vdisplay, int vrefresh, 298drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
305 bool interlaced, int margins) 299 int vrefresh, bool interlaced, int margins,
306{ 300 int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
307 /* 1) top/bottom margin size (% of height) - default: 1.8, */ 301{ /* 1) top/bottom margin size (% of height) - default: 1.8, */
308#define GTF_MARGIN_PERCENTAGE 18 302#define GTF_MARGIN_PERCENTAGE 18
309 /* 2) character cell horizontal granularity (pixels) - default 8 */ 303 /* 2) character cell horizontal granularity (pixels) - default 8 */
310#define GTF_CELL_GRAN 8 304#define GTF_CELL_GRAN 8
@@ -316,17 +310,9 @@ struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay,
316#define H_SYNC_PERCENT 8 310#define H_SYNC_PERCENT 8
317 /* min time of vsync + back porch (microsec) */ 311 /* min time of vsync + back porch (microsec) */
318#define MIN_VSYNC_PLUS_BP 550 312#define MIN_VSYNC_PLUS_BP 550
319 /* blanking formula gradient */
320#define GTF_M 600
321 /* blanking formula offset */
322#define GTF_C 40
323 /* blanking formula scaling factor */
324#define GTF_K 128
325 /* blanking formula scaling factor */
326#define GTF_J 20
327 /* C' and M' are part of the Blanking Duty Cycle computation */ 313 /* C' and M' are part of the Blanking Duty Cycle computation */
328#define GTF_C_PRIME (((GTF_C - GTF_J) * GTF_K / 256) + GTF_J) 314#define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
329#define GTF_M_PRIME (GTF_K * GTF_M / 256) 315#define GTF_M_PRIME (GTF_K * GTF_M / 256)
330 struct drm_display_mode *drm_mode; 316 struct drm_display_mode *drm_mode;
331 unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd; 317 unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
332 int top_margin, bottom_margin; 318 int top_margin, bottom_margin;
@@ -470,7 +456,48 @@ struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay,
470 456
471 return drm_mode; 457 return drm_mode;
472} 458}
459EXPORT_SYMBOL(drm_gtf_mode_complex);
460
461/**
462 * drm_gtf_mode - create the modeline based on GTF algorithm
463 *
464 * @dev :drm device
465 * @hdisplay :hdisplay size
466 * @vdisplay :vdisplay size
467 * @vrefresh :vrefresh rate.
468 * @interlaced :whether the interlace is supported
469 * @margins :whether the margin is supported
470 *
471 * LOCKING.
472 * none.
473 *
474 * return the modeline based on GTF algorithm
475 *
476 * This function is to create the modeline based on the GTF algorithm.
477 * Generalized Timing Formula is derived from:
478 * GTF Spreadsheet by Andy Morrish (1/5/97)
479 * available at http://www.vesa.org
480 *
481 * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
482 * What I have done is to translate it by using integer calculation.
483 * I also refer to the function of fb_get_mode in the file of
484 * drivers/video/fbmon.c
485 *
486 * Standard GTF parameters:
487 * M = 600
488 * C = 40
489 * K = 128
490 * J = 20
491 */
492struct drm_display_mode *
493drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
494 bool lace, int margins)
495{
496 return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh, lace,
497 margins, 600, 40 * 2, 128, 20 * 2);
498}
473EXPORT_SYMBOL(drm_gtf_mode); 499EXPORT_SYMBOL(drm_gtf_mode);
500
474/** 501/**
475 * drm_mode_set_name - set the name on a mode 502 * drm_mode_set_name - set the name on a mode
476 * @mode: name will be set in this mode 503 * @mode: name will be set in this mode
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index f74523a299c9..8eb3630ee67d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -797,6 +797,10 @@ extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
797extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, 797extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev,
798 int hdisplay, int vdisplay, int vrefresh, 798 int hdisplay, int vdisplay, int vrefresh,
799 bool interlaced, int margins); 799 bool interlaced, int margins);
800extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
801 int hdisplay, int vdisplay, int vrefresh,
802 bool interlaced, int margins, int GTF_M,
803 int GTF_2C, int GTF_K, int GTF_2J);
800extern int drm_add_modes_noedid(struct drm_connector *connector, 804extern int drm_add_modes_noedid(struct drm_connector *connector,
801 int hdisplay, int vdisplay); 805 int hdisplay, int vdisplay);
802 806