Commit c9c2625f authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-edid-fixes' into drm-core-next

* drm-edid-fixes:
  drm/edid: When checking duplicate standard modes, walked the probed list
  drm/edid: Fix sync polarity for secondary GTF curve
  drm/modes: Fix interlaced mode names
  drm/edid: Add secondary GTF curve support
  drm/edid: Strengthen the algorithm for standard mode codes
  drm/edid: Fix the HDTV hack.
  drm/edid: Extend range-based mode addition for EDID 1.4
  drm/edid: Add test for monitor reduced blanking support.
  drm/edid: Fix preferred mode parse for EDID 1.4
  drm/edid: Remove some silly comments
  drm/edid: Remove arbitrary EDID extension limit
  drm/edid: Add modes for Established Timings III section
  drm/edid: Reshuffle mode list construction to closer match the spec
  drm/edid: Remove a redundant check
  drm/edid: Remove some misleading comments
  drm/edid: Fix secondary block fetch.
parents c2b41276 522032da
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "drm.h" #include "drm.h"
#include "drmP.h" #include "drmP.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#include "drm_edid.h"
struct drm_prop_enum_list { struct drm_prop_enum_list {
int type; int type;
...@@ -2350,7 +2351,7 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, ...@@ -2350,7 +2351,7 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
struct edid *edid) struct edid *edid)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
int ret = 0; int ret = 0, size;
if (connector->edid_blob_ptr) if (connector->edid_blob_ptr)
drm_property_destroy_blob(dev, connector->edid_blob_ptr); drm_property_destroy_blob(dev, connector->edid_blob_ptr);
...@@ -2362,7 +2363,9 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, ...@@ -2362,7 +2363,9 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector,
return ret; return ret;
} }
connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 128, edid); size = EDID_LENGTH * (1 + edid->extensions);
connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
size, edid);
ret = drm_connector_property_set_value(connector, ret = drm_connector_property_set_value(connector,
dev->mode_config.edid_property, dev->mode_config.edid_property,
......
This diff is collapsed.
...@@ -258,8 +258,10 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, ...@@ -258,8 +258,10 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP;
/* 18/16. Find actual vertical frame frequency */ /* 18/16. Find actual vertical frame frequency */
/* ignore - just set the mode flag for interlaced */ /* ignore - just set the mode flag for interlaced */
if (interlaced) if (interlaced) {
drm_mode->vtotal *= 2; drm_mode->vtotal *= 2;
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
}
/* Fill the mode line name */ /* Fill the mode line name */
drm_mode_set_name(drm_mode); drm_mode_set_name(drm_mode);
if (reduced) if (reduced)
...@@ -268,43 +270,35 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, ...@@ -268,43 +270,35 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
else else
drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC | drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_NHSYNC); DRM_MODE_FLAG_NHSYNC);
if (interlaced)
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
return drm_mode; return drm_mode;
} }
EXPORT_SYMBOL(drm_cvt_mode); EXPORT_SYMBOL(drm_cvt_mode);
/** /**
* drm_gtf_mode - create the modeline based on GTF algorithm * drm_gtf_mode_complex - create the modeline based on full GTF algorithm
* *
* @dev :drm device * @dev :drm device
* @hdisplay :hdisplay size * @hdisplay :hdisplay size
* @vdisplay :vdisplay size * @vdisplay :vdisplay size
* @vrefresh :vrefresh rate. * @vrefresh :vrefresh rate.
* @interlaced :whether the interlace is supported * @interlaced :whether the interlace is supported
* @margins :whether the margin is supported * @margins :desired margin size
* @GTF_[MCKJ] :extended GTF formula parameters
* *
* LOCKING. * LOCKING.
* none. * none.
* *
* return the modeline based on GTF algorithm * return the modeline based on full GTF algorithm.
*
* This function is to create the modeline based on the GTF algorithm.
* Generalized Timing Formula is derived from:
* GTF Spreadsheet by Andy Morrish (1/5/97)
* available at http://www.vesa.org
* *
* And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c. * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
* What I have done is to translate it by using integer calculation. * in here multiplied by two. For a C of 40, pass in 80.
* I also refer to the function of fb_get_mode in the file of
* drivers/video/fbmon.c
*/ */
struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, struct drm_display_mode *
int vdisplay, int vrefresh, drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
bool interlaced, int margins) int vrefresh, bool interlaced, int margins,
{ int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
/* 1) top/bottom margin size (% of height) - default: 1.8, */ { /* 1) top/bottom margin size (% of height) - default: 1.8, */
#define GTF_MARGIN_PERCENTAGE 18 #define GTF_MARGIN_PERCENTAGE 18
/* 2) character cell horizontal granularity (pixels) - default 8 */ /* 2) character cell horizontal granularity (pixels) - default 8 */
#define GTF_CELL_GRAN 8 #define GTF_CELL_GRAN 8
...@@ -316,17 +310,9 @@ struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, ...@@ -316,17 +310,9 @@ struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay,
#define H_SYNC_PERCENT 8 #define H_SYNC_PERCENT 8
/* min time of vsync + back porch (microsec) */ /* min time of vsync + back porch (microsec) */
#define MIN_VSYNC_PLUS_BP 550 #define MIN_VSYNC_PLUS_BP 550
/* blanking formula gradient */
#define GTF_M 600
/* blanking formula offset */
#define GTF_C 40
/* blanking formula scaling factor */
#define GTF_K 128
/* blanking formula scaling factor */
#define GTF_J 20
/* C' and M' are part of the Blanking Duty Cycle computation */ /* C' and M' are part of the Blanking Duty Cycle computation */
#define GTF_C_PRIME (((GTF_C - GTF_J) * GTF_K / 256) + GTF_J) #define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
#define GTF_M_PRIME (GTF_K * GTF_M / 256) #define GTF_M_PRIME (GTF_K * GTF_M / 256)
struct drm_display_mode *drm_mode; struct drm_display_mode *drm_mode;
unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd; unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
int top_margin, bottom_margin; int top_margin, bottom_margin;
...@@ -460,17 +446,61 @@ struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, ...@@ -460,17 +446,61 @@ struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay,
drm_mode->clock = pixel_freq; drm_mode->clock = pixel_freq;
drm_mode_set_name(drm_mode);
drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
if (interlaced) { if (interlaced) {
drm_mode->vtotal *= 2; drm_mode->vtotal *= 2;
drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
} }
drm_mode_set_name(drm_mode);
if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40)
drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
else
drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC;
return drm_mode; return drm_mode;
} }
EXPORT_SYMBOL(drm_gtf_mode_complex);
/**
* drm_gtf_mode - create the modeline based on GTF algorithm
*
* @dev :drm device
* @hdisplay :hdisplay size
* @vdisplay :vdisplay size
* @vrefresh :vrefresh rate.
* @interlaced :whether the interlace is supported
* @margins :whether the margin is supported
*
* LOCKING.
* none.
*
* return the modeline based on GTF algorithm
*
* This function is to create the modeline based on the GTF algorithm.
* Generalized Timing Formula is derived from:
* GTF Spreadsheet by Andy Morrish (1/5/97)
* available at http://www.vesa.org
*
* And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
* What I have done is to translate it by using integer calculation.
* I also refer to the function of fb_get_mode in the file of
* drivers/video/fbmon.c
*
* Standard GTF parameters:
* M = 600
* C = 40
* K = 128
* J = 20
*/
struct drm_display_mode *
drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
bool lace, int margins)
{
return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh, lace,
margins, 600, 40 * 2, 128, 20 * 2);
}
EXPORT_SYMBOL(drm_gtf_mode); EXPORT_SYMBOL(drm_gtf_mode);
/** /**
* drm_mode_set_name - set the name on a mode * drm_mode_set_name - set the name on a mode
* @mode: name will be set in this mode * @mode: name will be set in this mode
...@@ -482,8 +512,11 @@ EXPORT_SYMBOL(drm_gtf_mode); ...@@ -482,8 +512,11 @@ EXPORT_SYMBOL(drm_gtf_mode);
*/ */
void drm_mode_set_name(struct drm_display_mode *mode) void drm_mode_set_name(struct drm_display_mode *mode)
{ {
snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay, bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
mode->vdisplay);
snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
mode->hdisplay, mode->vdisplay,
interlaced ? "i" : "");
} }
EXPORT_SYMBOL(drm_mode_set_name); EXPORT_SYMBOL(drm_mode_set_name);
......
...@@ -333,7 +333,7 @@ static struct device_attribute connector_attrs_opt1[] = { ...@@ -333,7 +333,7 @@ static struct device_attribute connector_attrs_opt1[] = {
static struct bin_attribute edid_attr = { static struct bin_attribute edid_attr = {
.attr.name = "edid", .attr.name = "edid",
.attr.mode = 0444, .attr.mode = 0444,
.size = 128, .size = 0,
.read = edid_show, .read = edid_show,
}; };
......
...@@ -450,17 +450,17 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) ...@@ -450,17 +450,17 @@ bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
{ {
int edid_info; int edid_info;
struct edid *edid; struct edid *edid;
unsigned char *raw;
edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE); edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
if (!edid_info) if (!edid_info)
return false; return false;
edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1), raw = rdev->bios + edid_info;
GFP_KERNEL); edid = kmalloc(EDID_LENGTH * (raw[0x7e] + 1), GFP_KERNEL);
if (edid == NULL) if (edid == NULL)
return false; return false;
memcpy((unsigned char *)edid, memcpy((unsigned char *)edid, raw, EDID_LENGTH * (raw[0x7e] + 1));
(unsigned char *)(rdev->bios + edid_info), EDID_LENGTH);
if (!drm_edid_is_valid(edid)) { if (!drm_edid_is_valid(edid)) {
kfree(edid); kfree(edid);
......
...@@ -666,8 +666,6 @@ extern void drm_fb_release(struct drm_file *file_priv); ...@@ -666,8 +666,6 @@ extern void drm_fb_release(struct drm_file *file_priv);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern struct edid *drm_get_edid(struct drm_connector *connector, extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
extern int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
unsigned char *buf, int len);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode); extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode);
...@@ -799,6 +797,10 @@ extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, ...@@ -799,6 +797,10 @@ extern struct drm_display_mode *drm_cvt_mode(struct drm_device *dev,
extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, extern struct drm_display_mode *drm_gtf_mode(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh, int hdisplay, int vdisplay, int vrefresh,
bool interlaced, int margins); bool interlaced, int margins);
extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
int hdisplay, int vdisplay, int vrefresh,
bool interlaced, int margins, int GTF_M,
int GTF_2C, int GTF_K, int GTF_2J);
extern int drm_add_modes_noedid(struct drm_connector *connector, extern int drm_add_modes_noedid(struct drm_connector *connector,
int hdisplay, int vdisplay); int hdisplay, int vdisplay);
......
...@@ -201,7 +201,4 @@ struct edid { ...@@ -201,7 +201,4 @@ struct edid {
#define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8)) #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
/* define the number of Extension EDID block */
#define DRM_MAX_EDID_EXT_NUM 4
#endif /* __DRM_EDID_H__ */ #endif /* __DRM_EDID_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment