drm: EDID endianness fixes.
authorMichel Dänzer <daenzer@vmware.com>
Mon, 15 Jun 2009 14:56:07 +0000 (16:56 +0200)
committerDave Airlie <airlied@redhat.com>
Thu, 18 Jun 2009 23:11:13 +0000 (09:11 +1000)
Mostly replacing bitfields with explicit masks and shifts.

Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/radeon/radeon_display.c
include/drm/drm_edid.h

index 801a0d0..7d08352 100644 (file)
@@ -252,16 +252,18 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
 {
        struct drm_display_mode *mode;
        int hsize = t->hsize * 8 + 248, vsize;
+       unsigned aspect_ratio = (t->vfreq_aspect & EDID_TIMING_ASPECT_MASK)
+               >> EDID_TIMING_ASPECT_SHIFT;
 
        mode = drm_mode_create(dev);
        if (!mode)
                return NULL;
 
-       if (t->aspect_ratio == 0)
+       if (aspect_ratio == 0)
                vsize = (hsize * 10) / 16;
-       else if (t->aspect_ratio == 1)
+       else if (aspect_ratio == 1)
                vsize = (hsize * 3) / 4;
-       else if (t->aspect_ratio == 2)
+       else if (aspect_ratio == 2)
                vsize = (hsize * 4) / 5;
        else
                vsize = (hsize * 9) / 16;
@@ -288,17 +290,24 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 {
        struct drm_display_mode *mode;
        struct detailed_pixel_timing *pt = &timing->data.pixel_data;
+       unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
+       unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
+       unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
+       unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
+       unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo;
+       unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo;
+       unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf);
+       unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
 
        /* ignore tiny modes */
-       if (((pt->hactive_hi << 8) | pt->hactive_lo) < 64 ||
-           ((pt->vactive_hi << 8) | pt->hactive_lo) < 64)
+       if (hactive < 64 || vactive < 64)
                return NULL;
 
-       if (pt->stereo) {
+       if (pt->misc & DRM_EDID_PT_STEREO) {
                printk(KERN_WARNING "stereo mode not supported\n");
                return NULL;
        }
-       if (!pt->separate_sync) {
+       if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
                printk(KERN_WARNING "integrated sync not supported\n");
                return NULL;
        }
@@ -310,41 +319,36 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        mode->type = DRM_MODE_TYPE_DRIVER;
 
        if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
-               timing->pixel_clock = 1088;
-
-       mode->clock = timing->pixel_clock * 10;
-
-       mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo;
-       mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) |
-                                             pt->hsync_offset_lo);
-       mode->hsync_end = mode->hsync_start +
-               ((pt->hsync_pulse_width_hi << 8) |
-                pt->hsync_pulse_width_lo);
-       mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo);
-
-       mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo;
-       mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 4) |
-                                             pt->vsync_offset_lo);
-       mode->vsync_end = mode->vsync_start +
-               ((pt->vsync_pulse_width_hi << 4) |
-                pt->vsync_pulse_width_lo);
-       mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo);
+               timing->pixel_clock = cpu_to_le16(1088);
+
+       mode->clock = le16_to_cpu(timing->pixel_clock) * 10;
+
+       mode->hdisplay = hactive;
+       mode->hsync_start = mode->hdisplay + hsync_offset;
+       mode->hsync_end = mode->hsync_start + hsync_pulse_width;
+       mode->htotal = mode->hdisplay + hblank;
+
+       mode->vdisplay = vactive;
+       mode->vsync_start = mode->vdisplay + vsync_offset;
+       mode->vsync_end = mode->vsync_start + vsync_pulse_width;
+       mode->vtotal = mode->vdisplay + vblank;
 
        drm_mode_set_name(mode);
 
-       if (pt->interlaced)
+       if (pt->misc & DRM_EDID_PT_INTERLACED)
                mode->flags |= DRM_MODE_FLAG_INTERLACE;
 
        if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
-               pt->hsync_positive = 1;
-               pt->vsync_positive = 1;
+               pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
        }
 
-       mode->flags |= pt->hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
-       mode->flags |= pt->vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+       mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ?
+               DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+       mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
+               DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
 
-       mode->width_mm = pt->width_mm_lo | (pt->width_mm_hi << 8);
-       mode->height_mm = pt->height_mm_lo | (pt->height_mm_hi << 8);
+       mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
+       mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
 
        if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
                mode->width_mm *= 10;
@@ -465,7 +469,7 @@ static int add_standard_modes(struct drm_connector *connector, struct edid *edid
                struct drm_display_mode *newmode;
 
                /* If std timings bytes are 1, 1 it's empty */
-               if (t->hsize == 1 && (t->aspect_ratio | t->vfreq) == 1)
+               if (t->hsize == 1 && t->vfreq_aspect == 1)
                        continue;
 
                newmode = drm_mode_std(dev, &edid->standard_timings[i]);
@@ -509,7 +513,7 @@ static int add_detailed_info(struct drm_connector *connector,
                                continue;
 
                        /* First detailed mode is preferred */
-                       if (i == 0 && edid->preferred_timing)
+                       if (i == 0 && (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING))
                                newmode->type |= DRM_MODE_TYPE_PREFERRED;
                        drm_mode_probed_add(connector, newmode);
 
@@ -767,22 +771,22 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
        if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
                edid_fixup_preferred(connector, quirks);
 
-       connector->display_info.serration_vsync = edid->serration_vsync;
-       connector->display_info.sync_on_green = edid->sync_on_green;
-       connector->display_info.composite_sync = edid->composite_sync;
-       connector->display_info.separate_syncs = edid->separate_syncs;
-       connector->display_info.blank_to_black = edid->blank_to_black;
-       connector->display_info.video_level = edid->video_level;
-       connector->display_info.digital = edid->digital;
+       connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0;
+       connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0;
+       connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0;
+       connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0;
+       connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0;
+       connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5;
+       connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0;
        connector->display_info.width_mm = edid->width_cm * 10;
        connector->display_info.height_mm = edid->height_cm * 10;
        connector->display_info.gamma = edid->gamma;
-       connector->display_info.gtf_supported = edid->default_gtf;
-       connector->display_info.standard_color = edid->standard_color;
-       connector->display_info.display_type = edid->display_type;
-       connector->display_info.active_off_supported = edid->pm_active_off;
-       connector->display_info.suspend_supported = edid->pm_suspend;
-       connector->display_info.standby_supported = edid->pm_standby;
+       connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0;
+       connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0;
+       connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3;
+       connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0;
+       connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0;
+       connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0;
        connector->display_info.gamma = edid->gamma;
 
        return num_modes;
index 5452bb9..3efcf1a 100644 (file)
@@ -351,7 +351,7 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
        radeon_i2c_do_lock(radeon_connector, 0);
        if (edid) {
                /* update digital bits here */
-               if (edid->digital)
+               if (edid->input & DRM_EDID_INPUT_DIGITAL)
                        radeon_connector->use_digital = 1;
                else
                        radeon_connector->use_digital = 0;
index a11cc9d..c263e4d 100644 (file)
 #define EDID_LENGTH 128
 #define DDC_ADDR 0x50
 
-#ifdef BIG_ENDIAN
-#error "EDID structure is little endian, need big endian versions"
-#else
-
 struct est_timings {
        u8 t1;
        u8 t2;
        u8 mfg_rsvd;
 } __attribute__((packed));
 
+/* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
+#define EDID_TIMING_ASPECT_SHIFT 0
+#define EDID_TIMING_ASPECT_MASK  (0x3 << EDID_TIMING_ASPECT_SHIFT)
+
+/* need to add 60 */
+#define EDID_TIMING_VFREQ_SHIFT  2
+#define EDID_TIMING_VFREQ_MASK   (0x3f << EDID_TIMING_VFREQ_SHIFT)
+
 struct std_timing {
        u8 hsize; /* need to multiply by 8 then add 248 */
-       u8 vfreq:6; /* need to add 60 */
-       u8 aspect_ratio:2; /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
+       u8 vfreq_aspect;
 } __attribute__((packed));
 
+#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 6)
+#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 5)
+#define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
+#define DRM_EDID_PT_STEREO         (1 << 2)
+#define DRM_EDID_PT_INTERLACED     (1 << 1)
+
 /* If detailed data is pixel timing */
 struct detailed_pixel_timing {
        u8 hactive_lo;
        u8 hblank_lo;
-       u8 hblank_hi:4;
-       u8 hactive_hi:4;
+       u8 hactive_hblank_hi;
        u8 vactive_lo;
        u8 vblank_lo;
-       u8 vblank_hi:4;
-       u8 vactive_hi:4;
+       u8 vactive_vblank_hi;
        u8 hsync_offset_lo;
        u8 hsync_pulse_width_lo;
-       u8 vsync_pulse_width_lo:4;
-       u8 vsync_offset_lo:4;
-       u8 vsync_pulse_width_hi:2;
-       u8 vsync_offset_hi:2;
-       u8 hsync_pulse_width_hi:2;
-       u8 hsync_offset_hi:2;
+       u8 vsync_offset_pulse_width_lo;
+       u8 hsync_vsync_offset_pulse_width_hi;
        u8 width_mm_lo;
        u8 height_mm_lo;
-       u8 height_mm_hi:4;
-       u8 width_mm_hi:4;
+       u8 width_height_mm_hi;
        u8 hborder;
        u8 vborder;
-       u8 unknown0:1;
-       u8 hsync_positive:1;
-       u8 vsync_positive:1;
-       u8 separate_sync:2;
-       u8 stereo:1;
-       u8 unknown6:1;
-       u8 interlaced:1;
+       u8 misc;
 } __attribute__((packed));
 
 /* If it's not pixel timing, it'll be one of the below */
@@ -88,18 +84,16 @@ struct detailed_data_monitor_range {
        u8 min_hfreq_khz;
        u8 max_hfreq_khz;
        u8 pixel_clock_mhz; /* need to multiply by 10 */
-       u16 sec_gtf_toggle; /* A000=use above, 20=use below */ /* FIXME: byte order */
+       __le16 sec_gtf_toggle; /* A000=use above, 20=use below */
        u8 hfreq_start_khz; /* need to multiply by 2 */
        u8 c; /* need to divide by 2 */
-       u16 m; /* FIXME: byte order */
+       __le16 m;
        u8 k;
        u8 j; /* need to divide by 2 */
 } __attribute__((packed));
 
 struct detailed_data_wpindex {
-       u8 white_y_lo:2;
-       u8 white_x_lo:2;
-       u8 pad:4;
+       u8 white_xy_lo; /* Upper 2 bits each */
        u8 white_x_hi;
        u8 white_y_hi;
        u8 gamma; /* need to divide by 100 then add 1 */
@@ -134,13 +128,29 @@ struct detailed_non_pixel {
 #define EDID_DETAIL_MONITOR_SERIAL 0xff
 
 struct detailed_timing {
-       u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
+       __le16 pixel_clock; /* need to multiply by 10 KHz */
        union {
                struct detailed_pixel_timing pixel_data;
                struct detailed_non_pixel other_data;
        } data;
 } __attribute__((packed));
 
+#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 7)
+#define DRM_EDID_INPUT_SYNC_ON_GREEN   (1 << 5)
+#define DRM_EDID_INPUT_COMPOSITE_SYNC  (1 << 4)
+#define DRM_EDID_INPUT_SEPARATE_SYNCS  (1 << 3)
+#define DRM_EDID_INPUT_BLANK_TO_BLACK  (1 << 2)
+#define DRM_EDID_INPUT_VIDEO_LEVEL     (3 << 1)
+#define DRM_EDID_INPUT_DIGITAL         (1 << 0) /* bits above must be zero if set */
+
+#define DRM_EDID_FEATURE_DEFAULT_GTF      (1 << 7)
+#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 6)
+#define DRM_EDID_FEATURE_STANDARD_COLOR   (1 << 5)
+#define DRM_EDID_FEATURE_DISPLAY_TYPE     (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
+#define DRM_EDID_FEATURE_PM_ACTIVE_OFF    (1 << 2)
+#define DRM_EDID_FEATURE_PM_SUSPEND       (1 << 1)
+#define DRM_EDID_FEATURE_PM_STANDBY       (1 << 0)
+
 struct edid {
        u8 header[8];
        /* Vendor & product info */
@@ -153,25 +163,11 @@ struct edid {
        u8 version;
        u8 revision;
        /* Display info: */
-       /*   input definition */
-       u8 serration_vsync:1;
-       u8 sync_on_green:1;
-       u8 composite_sync:1;
-       u8 separate_syncs:1;
-       u8 blank_to_black:1;
-       u8 video_level:2;
-       u8 digital:1; /* bits below must be zero if set */
+       u8 input;
        u8 width_cm;
        u8 height_cm;
        u8 gamma;
-       /*   feature support */
-       u8 default_gtf:1;
-       u8 preferred_timing:1;
-       u8 standard_color:1;
-       u8 display_type:2; /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
-       u8 pm_active_off:1;
-       u8 pm_suspend:1;
-       u8 pm_standby:1;
+       u8 features;
        /* Color characteristics */
        u8 red_green_lo;
        u8 black_white_lo;
@@ -195,8 +191,6 @@ struct edid {
        u8 checksum;
 } __attribute__((packed));
 
-#endif /* little endian structs */
-
 #define EDID_PRODUCT_ID(e) ((e)->prod_code[0] | ((e)->prod_code[1] << 8))
 
 #endif /* __DRM_EDID_H__ */