Finish bringing in LVDS code, re-add to Makefile. Needed other changes too:
- move EDID structures to drm_edid.h - add EDID info structure to drm_output - add a few routines to intel_display for getting current mode info - add some prototypes to intel_drv.h and drm_crtc.hmain
parent
c446bf50e3
commit
183cbd92dd
|
@ -20,7 +20,7 @@ r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
|
|||
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
|
||||
i810-objs := i810_drv.o i810_dma.o
|
||||
i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_fence.o \
|
||||
i915_buffer.o intel_display.o intel_crt.o \
|
||||
i915_buffer.o intel_display.o intel_crt.o intel_lvds.o \
|
||||
intel_sdvo.o intel_modes.o intel_i2c.o
|
||||
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
|
||||
nouveau_object.o nouveau_irq.o \
|
||||
|
|
|
@ -369,6 +369,7 @@ struct drm_output {
|
|||
/* xf86MonPtr MonInfo; */
|
||||
enum subpixel_order subpixel_order;
|
||||
int mm_width, mm_height;
|
||||
struct edid *monitor_info;
|
||||
char name[DRM_OUTPUT_LEN];
|
||||
const struct drm_output_funcs *funcs;
|
||||
void *driver_private;
|
||||
|
@ -455,6 +456,10 @@ extern int drm_mode_vrefresh(struct drm_display_mode *mode);
|
|||
extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
|
||||
int adjust_flags);
|
||||
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
|
||||
extern bool drm_initial_config(struct drm_device *dev, bool cangrow);
|
||||
extern void drm_framebuffer_set_object(struct drm_device *dev,
|
||||
unsigned long handle);
|
||||
extern bool drm_set_desired_modes(struct drm_device *dev);
|
||||
|
||||
#endif /* __DRM_CRTC_H__ */
|
||||
|
||||
|
|
|
@ -4,181 +4,14 @@
|
|||
*
|
||||
* DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
|
||||
* FB layer.
|
||||
* Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include "drmP.h"
|
||||
#include "drm_edid.h"
|
||||
|
||||
#define EDID_LENGTH 128
|
||||
#define DDC_ADDR 0x50
|
||||
|
||||
#ifdef BIG_ENDIAN
|
||||
#error "EDID structure is little endian, need big endian versions"
|
||||
#endif
|
||||
|
||||
struct est_timings {
|
||||
u8 t1;
|
||||
u8 t2;
|
||||
u8 mfg_rsvd;
|
||||
} __attribute__((packed));
|
||||
|
||||
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 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* 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 vactive_lo;
|
||||
u8 vblank_lo;
|
||||
u8 vblank_hi:4;
|
||||
u8 vactive_hi:4;
|
||||
u8 hsync_offset_lo;
|
||||
u8 hsync_pulse_width_lo;
|
||||
u8 vsync_pulse_width_lo:4;
|
||||
u8 vsync_offset_lo:4;
|
||||
u8 hsync_pulse_width_hi:2;
|
||||
u8 hsync_offset_hi:2;
|
||||
u8 vsync_pulse_width_hi:2;
|
||||
u8 vsync_offset_hi:2;
|
||||
u8 width_mm_lo;
|
||||
u8 height_mm_lo;
|
||||
u8 height_mm_hi:4;
|
||||
u8 width_mm_hi:4;
|
||||
u8 hborder;
|
||||
u8 vborder;
|
||||
u8 unknown0:1;
|
||||
u8 vsync_positive:1;
|
||||
u8 hsync_positive:1;
|
||||
u8 separate_sync:2;
|
||||
u8 stereo:1;
|
||||
u8 unknown6:1;
|
||||
u8 interlaced:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* If it's not pixel timing, it'll be one of the below */
|
||||
struct detailed_data_string {
|
||||
u8 str[13];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_monitor_range {
|
||||
u8 min_vfreq;
|
||||
u8 max_vfreq;
|
||||
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 */
|
||||
u8 hfreq_start_khz; /* need to multiply by 2 */
|
||||
u8 c; /* need to divide by 2 */
|
||||
u16 m; /* FIXME: byte order */
|
||||
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_x_hi;
|
||||
u8 white_y_hi;
|
||||
u8 gamma; /* need to divide by 100 then add 1 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_color_point {
|
||||
u8 windex1;
|
||||
u8 wpindex1[3];
|
||||
u8 windex2;
|
||||
u8 wpindex2[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_non_pixel {
|
||||
u8 pad1;
|
||||
u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
|
||||
fb=color point data, fa=standard timing data,
|
||||
f9=undefined, f8=mfg. reserved */
|
||||
u8 pad2;
|
||||
union {
|
||||
struct detailed_data_string str;
|
||||
struct detailed_data_monitor_range range;
|
||||
struct detailed_data_wpindex color;
|
||||
struct std_timing timings[5];
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EDID_DETAIL_STD_MODES 0xfa
|
||||
#define EDID_DETAIL_MONITOR_CPDATA 0xfb
|
||||
#define EDID_DETAIL_MONITOR_NAME 0xfc
|
||||
#define EDID_DETAIL_MONITOR_RANGE 0xfd
|
||||
#define EDID_DETAIL_MONITOR_STRING 0xfe
|
||||
#define EDID_DETAIL_MONITOR_SERIAL 0xff
|
||||
|
||||
struct detailed_timing {
|
||||
u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
|
||||
union {
|
||||
struct detailed_pixel_timing pixel_data;
|
||||
struct detailed_non_pixel other_data;
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct edid {
|
||||
u8 header[8];
|
||||
/* Vendor & product info */
|
||||
u16 mfg_id; /* FIXME: byte order */
|
||||
u16 prod_code; /* FIXME: byte order */
|
||||
u32 serial; /* FIXME: byte order */
|
||||
u8 mfg_week;
|
||||
u8 mfg_year;
|
||||
/* EDID version */
|
||||
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 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;
|
||||
/* Color characteristics */
|
||||
u8 red_green_lo;
|
||||
u8 black_white_lo;
|
||||
u8 red_x;
|
||||
u8 red_y;
|
||||
u8 green_x;
|
||||
u8 green_y;
|
||||
u8 blue_x;
|
||||
u8 blue_y;
|
||||
u8 white_x;
|
||||
u8 white_y;
|
||||
/* Est. timings and mfg rsvd timings*/
|
||||
struct est_timings established_timings;
|
||||
/* Standard timings 1-8*/
|
||||
struct std_timing standard_timings[8];
|
||||
/* Detailing timings 1-4 */
|
||||
struct detailed_timing detailed_timings[4];
|
||||
/* Number of 128 byte ext. blocks */
|
||||
u8 extensions;
|
||||
/* Checksum */
|
||||
u8 checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Valid EDID header has these bytes */
|
||||
static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
#ifndef __DRM_EDID_H__
|
||||
#define __DRM_EDID_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define EDID_LENGTH 128
|
||||
#define DDC_ADDR 0x50
|
||||
|
||||
#ifdef BIG_ENDIAN
|
||||
#error "EDID structure is little endian, need big endian versions"
|
||||
#endif
|
||||
|
||||
struct est_timings {
|
||||
u8 t1;
|
||||
u8 t2;
|
||||
u8 mfg_rsvd;
|
||||
} __attribute__((packed));
|
||||
|
||||
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 */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* 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 vactive_lo;
|
||||
u8 vblank_lo;
|
||||
u8 vblank_hi:4;
|
||||
u8 vactive_hi:4;
|
||||
u8 hsync_offset_lo;
|
||||
u8 hsync_pulse_width_lo;
|
||||
u8 vsync_pulse_width_lo:4;
|
||||
u8 vsync_offset_lo:4;
|
||||
u8 hsync_pulse_width_hi:2;
|
||||
u8 hsync_offset_hi:2;
|
||||
u8 vsync_pulse_width_hi:2;
|
||||
u8 vsync_offset_hi:2;
|
||||
u8 width_mm_lo;
|
||||
u8 height_mm_lo;
|
||||
u8 height_mm_hi:4;
|
||||
u8 width_mm_hi:4;
|
||||
u8 hborder;
|
||||
u8 vborder;
|
||||
u8 unknown0:1;
|
||||
u8 vsync_positive:1;
|
||||
u8 hsync_positive:1;
|
||||
u8 separate_sync:2;
|
||||
u8 stereo:1;
|
||||
u8 unknown6:1;
|
||||
u8 interlaced:1;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* If it's not pixel timing, it'll be one of the below */
|
||||
struct detailed_data_string {
|
||||
u8 str[13];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_monitor_range {
|
||||
u8 min_vfreq;
|
||||
u8 max_vfreq;
|
||||
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 */
|
||||
u8 hfreq_start_khz; /* need to multiply by 2 */
|
||||
u8 c; /* need to divide by 2 */
|
||||
u16 m; /* FIXME: byte order */
|
||||
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_x_hi;
|
||||
u8 white_y_hi;
|
||||
u8 gamma; /* need to divide by 100 then add 1 */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_data_color_point {
|
||||
u8 windex1;
|
||||
u8 wpindex1[3];
|
||||
u8 windex2;
|
||||
u8 wpindex2[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct detailed_non_pixel {
|
||||
u8 pad1;
|
||||
u8 type; /* ff=serial, fe=string, fd=monitor range, fc=monitor name
|
||||
fb=color point data, fa=standard timing data,
|
||||
f9=undefined, f8=mfg. reserved */
|
||||
u8 pad2;
|
||||
union {
|
||||
struct detailed_data_string str;
|
||||
struct detailed_data_monitor_range range;
|
||||
struct detailed_data_wpindex color;
|
||||
struct std_timing timings[5];
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define EDID_DETAIL_STD_MODES 0xfa
|
||||
#define EDID_DETAIL_MONITOR_CPDATA 0xfb
|
||||
#define EDID_DETAIL_MONITOR_NAME 0xfc
|
||||
#define EDID_DETAIL_MONITOR_RANGE 0xfd
|
||||
#define EDID_DETAIL_MONITOR_STRING 0xfe
|
||||
#define EDID_DETAIL_MONITOR_SERIAL 0xff
|
||||
|
||||
struct detailed_timing {
|
||||
u16 pixel_clock; /* need to multiply by 10 KHz */ /* FIXME: byte order */
|
||||
union {
|
||||
struct detailed_pixel_timing pixel_data;
|
||||
struct detailed_non_pixel other_data;
|
||||
} data;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct edid {
|
||||
u8 header[8];
|
||||
/* Vendor & product info */
|
||||
u16 mfg_id; /* FIXME: byte order */
|
||||
u16 prod_code; /* FIXME: byte order */
|
||||
u32 serial; /* FIXME: byte order */
|
||||
u8 mfg_week;
|
||||
u8 mfg_year;
|
||||
/* EDID version */
|
||||
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 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;
|
||||
/* Color characteristics */
|
||||
u8 red_green_lo;
|
||||
u8 black_white_lo;
|
||||
u8 red_x;
|
||||
u8 red_y;
|
||||
u8 green_x;
|
||||
u8 green_y;
|
||||
u8 blue_x;
|
||||
u8 blue_y;
|
||||
u8 white_x;
|
||||
u8 white_y;
|
||||
/* Est. timings and mfg rsvd timings*/
|
||||
struct est_timings established_timings;
|
||||
/* Standard timings 1-8*/
|
||||
struct std_timing standard_timings[8];
|
||||
/* Detailing timings 1-4 */
|
||||
struct detailed_timing detailed_timings[4];
|
||||
/* Number of 128 byte ext. blocks */
|
||||
u8 extensions;
|
||||
/* Checksum */
|
||||
u8 checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* __DRM_EDID_H__ */
|
|
@ -26,8 +26,6 @@
|
|||
|
||||
#include <linux/i2c.h>
|
||||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
@ -973,10 +971,115 @@ static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
|
|||
intel_crtc_load_lut(crtc);
|
||||
}
|
||||
|
||||
/* Returns the clock of the currently programmed mode of the given pipe. */
|
||||
static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B);
|
||||
u32 fp;
|
||||
intel_clock_t clock;
|
||||
|
||||
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
|
||||
fp = I915_READ((pipe == 0) ? FPA0 : FPB0);
|
||||
else
|
||||
fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
|
||||
|
||||
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
|
||||
clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
|
||||
clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
|
||||
if (IS_I9XX(dev)) {
|
||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
||||
|
||||
switch (dpll & DPLL_MODE_MASK) {
|
||||
case DPLLB_MODE_DAC_SERIAL:
|
||||
clock.p2 = dpll & DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 ?
|
||||
5 : 10;
|
||||
break;
|
||||
case DPLLB_MODE_LVDS:
|
||||
clock.p2 = dpll & DPLLB_LVDS_P2_CLOCK_DIV_7 ?
|
||||
7 : 14;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unknown DPLL mode %08x in programmed "
|
||||
"mode\n", (int)(dpll & DPLL_MODE_MASK));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XXX: Handle the 100Mhz refclk */
|
||||
i9xx_clock(96000, &clock);
|
||||
} else {
|
||||
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
|
||||
|
||||
if (is_lvds) {
|
||||
clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT);
|
||||
clock.p2 = 14;
|
||||
|
||||
if ((dpll & PLL_REF_INPUT_MASK) ==
|
||||
PLLB_REF_INPUT_SPREADSPECTRUMIN) {
|
||||
/* XXX: might not be 66MHz */
|
||||
i8xx_clock(66000, &clock);
|
||||
} else
|
||||
i8xx_clock(48000, &clock);
|
||||
} else {
|
||||
if (dpll & PLL_P1_DIVIDE_BY_TWO)
|
||||
clock.p1 = 2;
|
||||
else {
|
||||
clock.p1 = ((dpll & DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
|
||||
DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
|
||||
}
|
||||
if (dpll & PLL_P2_DIVIDE_BY_4)
|
||||
clock.p2 = 4;
|
||||
else
|
||||
clock.p2 = 2;
|
||||
|
||||
i8xx_clock(48000, &clock);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: It would be nice to validate the clocks, but we can't reuse
|
||||
* i830PllIsValid() because it relies on the xf86_config output
|
||||
* configuration being accurate, which it isn't necessarily.
|
||||
*/
|
||||
|
||||
return clock.dot;
|
||||
}
|
||||
|
||||
/** Returns the currently programmed mode of the given pipe. */
|
||||
struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct intel_crtc *intel_crtc = crtc->driver_private;
|
||||
int pipe = intel_crtc->pipe;
|
||||
struct drm_display_mode *mode;
|
||||
int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
|
||||
int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
|
||||
int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
|
||||
int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
|
||||
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
mode->clock = intel_crtc_clock_get(dev, crtc);
|
||||
mode->hdisplay = (htot & 0xffff) + 1;
|
||||
mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
|
||||
mode->hsync_start = (hsync & 0xffff) + 1;
|
||||
mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
|
||||
mode->vdisplay = (vtot & 0xffff) + 1;
|
||||
mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
|
||||
mode->vsync_start = (vsync & 0xffff) + 1;
|
||||
mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
|
||||
/* FIXME: pull name generation into a common routine */
|
||||
snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay,
|
||||
mode->vdisplay);
|
||||
drm_mode_set_crtcinfo(mode, 0);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs intel_crtc_funcs = {
|
||||
|
@ -1039,9 +1142,11 @@ static void intel_setup_outputs(drm_device_t *dev)
|
|||
|
||||
intel_crt_init(dev);
|
||||
|
||||
#if 0
|
||||
/* Set up integrated LVDS */
|
||||
if (IS_MOBILE(dev) && !IS_I830(dev))
|
||||
intel_lvds_init(dev);
|
||||
#endif
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
intel_sdvo_init(dev, SDVOB);
|
||||
|
@ -1105,6 +1210,7 @@ void intel_modeset_init(drm_device_t *dev)
|
|||
intel_setup_outputs(dev);
|
||||
|
||||
drm_initial_config(dev, false);
|
||||
drm_set_desired_modes(dev);
|
||||
}
|
||||
|
||||
void intel_modeset_cleanup(drm_device_t *dev)
|
||||
|
|
|
@ -71,4 +71,7 @@ extern void intel_lvds_init(drm_device_t *dev);
|
|||
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
|
||||
extern void intel_output_prepare (struct drm_output *output);
|
||||
extern void intel_output_commit (struct drm_output *output);
|
||||
extern struct drm_display_mode *intel_crtc_mode_get(drm_device_t *dev,
|
||||
struct drm_crtc *crtc);
|
||||
|
||||
#endif /* __INTEL_DRV_H__ */
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "drmP.h"
|
||||
#include "drm.h"
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_edid.h"
|
||||
#include "intel_drv.h"
|
||||
#include "i915_drm.h"
|
||||
#include "i915_drv.h"
|
||||
|
@ -262,7 +263,7 @@ static int intel_lvds_get_modes(struct drm_output *output)
|
|||
struct intel_output *intel_output = output->driver_private;
|
||||
struct drm_device *dev = output->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_monitor_info *edid_mon;
|
||||
struct edid *edid_info;
|
||||
int ret = 0;
|
||||
|
||||
intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
|
||||
|
@ -276,23 +277,29 @@ static int intel_lvds_get_modes(struct drm_output *output)
|
|||
ret = intel_ddc_get_modes(output);
|
||||
if (ret)
|
||||
return ret;
|
||||
#if 0
|
||||
|
||||
/* Didn't get an EDID */
|
||||
if (!output->monitor_info) {
|
||||
edid_mon = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL);
|
||||
if (edid_mon) {
|
||||
struct detailed_data_monitor_range *edid_range;
|
||||
edid_info = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL);
|
||||
if (!edid_info)
|
||||
goto out;
|
||||
|
||||
edid_info->detailed_timings[0].data.other_data.type =
|
||||
EDID_DETAIL_MONITOR_RANGE;
|
||||
edid_range = &edid_info->detailed_timings[0].data.other_data.data.range;
|
||||
|
||||
/* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
edid_mon->det_mon[0].type = DS_RANGES;
|
||||
edid_mon->det_mon[0].section.ranges.min_v = 0;
|
||||
edid_mon->det_mon[0].section.ranges.max_v = 200;
|
||||
edid_mon->det_mon[0].section.ranges.min_h = 0;
|
||||
edid_mon->det_mon[0].section.ranges.max_h = 200;
|
||||
edid_range->min_vfreq = 0;
|
||||
edid_range->max_vfreq = 200;
|
||||
edid_range->min_hfreq_khz = 0;
|
||||
edid_range->max_hfreq_khz = 200;
|
||||
output->monitor_info = edid_info;
|
||||
}
|
||||
|
||||
output->monitor_info = edid_mon;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
out:
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode =
|
||||
drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
|
||||
|
@ -322,13 +329,19 @@ static const struct drm_output_funcs intel_lvds_output_funcs = {
|
|||
.cleanup = intel_lvds_destroy
|
||||
};
|
||||
|
||||
void
|
||||
intel_lvds_init(struct drm_device *dev)
|
||||
/**
|
||||
* intel_lvds_init - setup LVDS outputs on this device
|
||||
* @dev: drm device
|
||||
*
|
||||
* Create the output, register the LVDS DDC bus, and try to figure out what
|
||||
* modes we can display on the LVDS panel (if present).
|
||||
*/
|
||||
void intel_lvds_init(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_output *output;
|
||||
struct intel_output *intel_output;
|
||||
struct drm_display_mode *modes, scan, bios_mode;
|
||||
struct drm_display_mode *scan; /* *modes, *bios_mode; */
|
||||
|
||||
output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS");
|
||||
if (!output)
|
||||
|
@ -356,37 +369,43 @@ intel_lvds_init(struct drm_device *dev)
|
|||
break;
|
||||
}
|
||||
|
||||
if (scan != NULL)
|
||||
if (scan)
|
||||
dev_priv->panel_fixed_mode = scan;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If we didn't get EDID, try checking if the panel is already turned
|
||||
* on. If so, assume that whatever is currently programmed is the
|
||||
* correct mode.
|
||||
*/
|
||||
if (dev_priv->panel_fixed_mode == NULL) {
|
||||
if (!dev_priv->panel_fixed_mode) {
|
||||
u32 lvds = I915_READ(LVDS);
|
||||
int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
|
||||
struct drm_crtc_config *crtc_config = dev->crtc_config;
|
||||
struct drm_crtc *crtc = crtc_config->crtc[pipe];
|
||||
struct drm_crtc_config *crtc_config = &dev->crtc_config;
|
||||
struct drm_crtc *crtc;
|
||||
/* FIXME: need drm_crtc_from_pipe */
|
||||
//crtc = drm_crtc_from_pipe(crtc_config, pipe);
|
||||
|
||||
if (lvds & LVDS_PORT_EN) {
|
||||
dev_priv->panel_fixed_mode = intel_crtc_mode_get(pScrn, crtc);
|
||||
if (dev_priv->panel_fixed_mode != NULL)
|
||||
dev_priv->panel_fixed_mode->type |= M_T_PREFERRED;
|
||||
if (lvds & LVDS_PORT_EN && 0) {
|
||||
dev_priv->panel_fixed_mode =
|
||||
intel_crtc_mode_get(dev, crtc);
|
||||
if (dev_priv->panel_fixed_mode)
|
||||
dev_priv->panel_fixed_mode->type |=
|
||||
DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the LVDS fixed mode out of the BIOS. We should support LVDS with
|
||||
* the BIOS being unavailable or broken, but lack the configuration options
|
||||
* for now.
|
||||
/* No BIOS poking yet... */
|
||||
#if 0
|
||||
/* Get the LVDS fixed mode out of the BIOS. We should support LVDS
|
||||
* with the BIOS being unavailable or broken, but lack the
|
||||
* configuration options for now.
|
||||
*/
|
||||
bios_mode = intel_bios_get_panel_mode(pScrn);
|
||||
if (bios_mode != NULL) {
|
||||
if (dev_priv->panel_fixed_mode != NULL) {
|
||||
if (dev_priv->debug_modes &&
|
||||
!xf86ModesEqual(dev_priv->panel_fixed_mode, bios_mode))
|
||||
!xf86ModesEqual(dev_priv->panel_fixed_mode,
|
||||
bios_mode))
|
||||
{
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"BIOS panel mode data doesn't match probed data, "
|
||||
|
@ -439,35 +458,3 @@ intel_lvds_init(struct drm_device *dev)
|
|||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* intel_lvds_init - setup LVDS outputs on this device
|
||||
* @dev: drm device
|
||||
*
|
||||
* Create the output, register the LVDS DDC bus, and try to figure out what
|
||||
* modes we can display on the LVDS panel (if present).
|
||||
*/
|
||||
void intel_lvds_init(drm_device_t *dev)
|
||||
{
|
||||
struct drm_output *output;
|
||||
struct intel_output *intel_output;
|
||||
int modes;
|
||||
|
||||
output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS");
|
||||
if (!output)
|
||||
return;
|
||||
|
||||
intel_output = kmalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||
if (!intel_output) {
|
||||
drm_output_destroy(output);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_output->type = INTEL_OUTPUT_LVDS;
|
||||
output->driver_private = intel_output;
|
||||
output->subpixel_order = SubPixelHorizontalRGB;
|
||||
output->interlace_allowed = 0;
|
||||
output->doublescan_allowed = 0;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue