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.h
main
Jesse Barnes 2007-04-10 09:47:37 -07:00
parent c446bf50e3
commit 183cbd92dd
7 changed files with 350 additions and 240 deletions

View File

@ -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 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 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-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 intel_sdvo.o intel_modes.o intel_i2c.o
nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
nouveau_object.o nouveau_irq.o \ nouveau_object.o nouveau_irq.o \

View File

@ -369,6 +369,7 @@ struct drm_output {
/* xf86MonPtr MonInfo; */ /* xf86MonPtr MonInfo; */
enum subpixel_order subpixel_order; enum subpixel_order subpixel_order;
int mm_width, mm_height; int mm_width, mm_height;
struct edid *monitor_info;
char name[DRM_OUTPUT_LEN]; char name[DRM_OUTPUT_LEN];
const struct drm_output_funcs *funcs; const struct drm_output_funcs *funcs;
void *driver_private; 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, extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
int adjust_flags); int adjust_flags);
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev); 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__ */ #endif /* __DRM_CRTC_H__ */

View File

@ -4,181 +4,14 @@
* *
* DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from * DDC probing routines (drm_ddc_read & drm_do_probe_ddc_edid) originally from
* FB layer. * FB layer.
* Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
*/ */
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include "drmP.h" #include "drmP.h"
#include "drm_edid.h"
#define EDID_LENGTH 128 /* Valid EDID header has these bytes */
#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));
static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; static u8 edid_header[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
/** /**

176
linux-core/drm_edid.h Normal file
View File

@ -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__ */

View File

@ -26,8 +26,6 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include "drmP.h" #include "drmP.h"
#include "drm.h"
#include "drm_crtc.h"
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.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); 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_display_mode *intel_crtc_mode_get(drm_device_t *dev,
struct drm_crtc *crtc) struct drm_crtc *crtc)
{ {
return NULL; 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 = { static const struct drm_crtc_funcs intel_crtc_funcs = {
@ -1017,7 +1120,7 @@ void intel_crtc_init(drm_device_t *dev, int pipe)
crtc->driver_private = intel_crtc; crtc->driver_private = intel_crtc;
} }
int intel_output_clones (drm_device_t *dev, int type_mask) int intel_output_clones(drm_device_t *dev, int type_mask)
{ {
int index_mask = 0; int index_mask = 0;
struct drm_output *output; struct drm_output *output;
@ -1039,9 +1142,11 @@ static void intel_setup_outputs(drm_device_t *dev)
intel_crt_init(dev); intel_crt_init(dev);
#if 0
/* Set up integrated LVDS */ /* Set up integrated LVDS */
if (IS_MOBILE(dev) && !IS_I830(dev)) if (IS_MOBILE(dev) && !IS_I830(dev))
intel_lvds_init(dev); intel_lvds_init(dev);
#endif
if (IS_I9XX(dev)) { if (IS_I9XX(dev)) {
intel_sdvo_init(dev, SDVOB); intel_sdvo_init(dev, SDVOB);
@ -1105,6 +1210,7 @@ void intel_modeset_init(drm_device_t *dev)
intel_setup_outputs(dev); intel_setup_outputs(dev);
drm_initial_config(dev, false); drm_initial_config(dev, false);
drm_set_desired_modes(dev);
} }
void intel_modeset_cleanup(drm_device_t *dev) void intel_modeset_cleanup(drm_device_t *dev)

View File

@ -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_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_output_prepare (struct drm_output *output); extern void intel_output_prepare (struct drm_output *output);
extern void intel_output_commit (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__ */ #endif /* __INTEL_DRV_H__ */

View File

@ -31,6 +31,7 @@
#include "drmP.h" #include "drmP.h"
#include "drm.h" #include "drm.h"
#include "drm_crtc.h" #include "drm_crtc.h"
#include "drm_edid.h"
#include "intel_drv.h" #include "intel_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.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 intel_output *intel_output = output->driver_private;
struct drm_device *dev = output->dev; struct drm_device *dev = output->dev;
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_monitor_info *edid_mon; struct edid *edid_info;
int ret = 0; int ret = 0;
intel_output->ddc_bus = intel_i2c_create(dev, GPIOC, "LVDSDDC_C"); 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); ret = intel_ddc_get_modes(output);
if (ret) if (ret)
return ret; return ret;
#if 0
/* Didn't get an EDID */
if (!output->monitor_info) { if (!output->monitor_info) {
edid_mon = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL); struct detailed_data_monitor_range *edid_range;
if (edid_mon) { edid_info = kzalloc(sizeof(*output->monitor_info), GFP_KERNEL);
/* Set wide sync ranges so we get all modes if (!edid_info)
* handed to valid_mode for checking goto out;
*/
edid_mon->det_mon[0].type = DS_RANGES; edid_info->detailed_timings[0].data.other_data.type =
edid_mon->det_mon[0].section.ranges.min_v = 0; EDID_DETAIL_MONITOR_RANGE;
edid_mon->det_mon[0].section.ranges.max_v = 200; edid_range = &edid_info->detailed_timings[0].data.other_data.data.range;
edid_mon->det_mon[0].section.ranges.min_h = 0;
edid_mon->det_mon[0].section.ranges.max_h = 200; /* Set wide sync ranges so we get all modes
* handed to valid_mode for checking
output->monitor_info = edid_mon; */
} 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;
} }
#endif
out:
if (dev_priv->panel_fixed_mode != NULL) { if (dev_priv->panel_fixed_mode != NULL) {
struct drm_display_mode *mode = struct drm_display_mode *mode =
drm_mode_duplicate(dev, dev_priv->panel_fixed_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 .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; drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_output *output; struct drm_output *output;
struct intel_output *intel_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"); output = drm_output_create(dev, &intel_lvds_output_funcs, "LVDS");
if (!output) if (!output)
@ -356,37 +369,43 @@ intel_lvds_init(struct drm_device *dev)
break; break;
} }
if (scan != NULL) if (scan)
dev_priv->panel_fixed_mode = scan; dev_priv->panel_fixed_mode = scan;
#if 0
/* /*
* If we didn't get EDID, try checking if the panel is already turned * 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 * on. If so, assume that whatever is currently programmed is the
* correct mode. * correct mode.
*/ */
if (dev_priv->panel_fixed_mode == NULL) { if (!dev_priv->panel_fixed_mode) {
u32 lvds = I915_READ(LVDS); u32 lvds = I915_READ(LVDS);
int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; int pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
struct drm_crtc_config *crtc_config = dev->crtc_config; struct drm_crtc_config *crtc_config = &dev->crtc_config;
struct drm_crtc *crtc = crtc_config->crtc[pipe]; struct drm_crtc *crtc;
/* FIXME: need drm_crtc_from_pipe */
if (lvds & LVDS_PORT_EN) { //crtc = drm_crtc_from_pipe(crtc_config, pipe);
dev_priv->panel_fixed_mode = intel_crtc_mode_get(pScrn, crtc);
if (dev_priv->panel_fixed_mode != NULL) if (lvds & LVDS_PORT_EN && 0) {
dev_priv->panel_fixed_mode->type |= M_T_PREFERRED; 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 /* No BIOS poking yet... */
* the BIOS being unavailable or broken, but lack the configuration options #if 0
* for now. /* 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); bios_mode = intel_bios_get_panel_mode(pScrn);
if (bios_mode != NULL) { if (bios_mode != NULL) {
if (dev_priv->panel_fixed_mode != NULL) { if (dev_priv->panel_fixed_mode != NULL) {
if (dev_priv->debug_modes && 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, xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"BIOS panel mode data doesn't match probed data, " "BIOS panel mode data doesn't match probed data, "
@ -439,35 +458,3 @@ intel_lvds_init(struct drm_device *dev)
#endif #endif
return; 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