提交 9f7bc6ac 编写于 作者: D Dave Airlie

Merge branch 'gma500-next' of git://github.com/patjak/drm-gma500 into drm-next

Patrik writes:

I haven't had much review or testing on other platforms than Poulsbo but
at least the following Cedarview bug has been squashed and no
regressions reported: https://bugs.freedesktop.org/show_bug.cgi?id=58527

* 'gma500-next' of git://github.com/patjak/drm-gma500:
  drm/gma500: Add debugging info to psb_gtt_restore()
  drm/gma500: Check connector status before restoring sdvo
  gma500:fix build failure for 3.9-rc5
  drm/gma500: Fix hibernation problems on sdvo encoders
  drm/gma500: Add hooks for hibernation
  drm/gma500: Activate the gtt rebuild on suspend/resume
  drm/gma500: Add support for rebuilding the gtt
  drm/gma500: Change fb name so pm-utils doesn't apply quirks
  gma500: Make VGA and HDMI connector hotpluggable
  drm/gma500: Clean up various defines
  drm/gma500: Remove unnecessary function exposure
  drm/gma500: Type clock limits directly into array and remove defines
  drm/gma500: Calculate clock in one function instead of three identical
  drm/gma500: Remove unused i8xx clock limits
  gma500: medfield: Fix possible NULL pointer dereference
  drivers: gpu: drm: gma500: Replaced calls kzalloc & memcpy with kmemdup
  gma500: remove unused drm_psb_no_fb
......@@ -2,10 +2,15 @@ config DRM_GMA500
tristate "Intel GMA5/600 KMS Framebuffer"
depends on DRM && PCI && X86
select FB_CFB_COPYAREA
select FB_CFB_FILLRECT
select FB_CFB_IMAGEBLIT
select DRM_KMS_HELPER
select DRM_TTM
select FB_CFB_FILLRECT
select FB_CFB_IMAGEBLIT
select DRM_KMS_HELPER
select DRM_TTM
# GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
select ACPI_VIDEO if ACPI
select BACKLIGHT_CLASS_DEVICE if ACPI
select VIDEO_OUTPUT_CONTROL if ACPI
select INPUT if ACPI
help
Say yes for an experimental 2D KMS framebuffer driver for the
Intel GMA500 ('Poulsbo') and other Intel IMG based graphics
......
......@@ -276,6 +276,7 @@ void cdv_intel_crt_init(struct drm_device *dev,
goto failed_connector;
connector = &psb_intel_connector->base;
connector->polled = DRM_CONNECTOR_POLL_HPD;
drm_connector_init(dev, connector,
&cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
......
......@@ -319,6 +319,7 @@ void cdv_hdmi_init(struct drm_device *dev,
goto err_priv;
connector = &psb_intel_connector->base;
connector->polled = DRM_CONNECTOR_POLL_HPD;
encoder = &psb_intel_encoder->base;
drm_connector_init(dev, connector,
&cdv_hdmi_connector_funcs,
......
......@@ -431,7 +431,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
fbdev->psb_fb_helper.fbdev = info;
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
strcpy(info->fix.id, "psbfb");
strcpy(info->fix.id, "psbdrmfb");
info->flags = FBINFO_DEFAULT;
if (dev_priv->ops->accel_2d && pitch_lines > 8) /* 2D engine */
......
......@@ -80,7 +80,8 @@ static u32 __iomem *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
* the GTT. This is protected via the gtt mutex which the caller
* must hold.
*/
static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r,
int resume)
{
u32 __iomem *gtt_slot;
u32 pte;
......@@ -97,8 +98,10 @@ static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
gtt_slot = psb_gtt_entry(dev, r);
pages = r->pages;
/* Make sure changes are visible to the GPU */
set_pages_array_wc(pages, r->npage);
if (!resume) {
/* Make sure changes are visible to the GPU */
set_pages_array_wc(pages, r->npage);
}
/* Write our page entries into the GTT itself */
for (i = r->roll; i < r->npage; i++) {
......@@ -269,7 +272,7 @@ int psb_gtt_pin(struct gtt_range *gt)
ret = psb_gtt_attach_pages(gt);
if (ret < 0)
goto out;
ret = psb_gtt_insert(dev, gt);
ret = psb_gtt_insert(dev, gt, 0);
if (ret < 0) {
psb_gtt_detach_pages(gt);
goto out;
......@@ -421,9 +424,11 @@ int psb_gtt_init(struct drm_device *dev, int resume)
int ret = 0;
uint32_t pte;
mutex_init(&dev_priv->gtt_mutex);
if (!resume) {
mutex_init(&dev_priv->gtt_mutex);
psb_gtt_alloc(dev);
}
psb_gtt_alloc(dev);
pg = &dev_priv->gtt;
/* Enable the GTT */
......@@ -505,7 +510,8 @@ int psb_gtt_init(struct drm_device *dev, int resume)
/*
* Map the GTT and the stolen memory area
*/
dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
if (!resume)
dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
gtt_pages << PAGE_SHIFT);
if (!dev_priv->gtt_map) {
dev_err(dev->dev, "Failure to map gtt.\n");
......@@ -513,7 +519,9 @@ int psb_gtt_init(struct drm_device *dev, int resume)
goto out_err;
}
dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
if (!resume)
dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base,
stolen_size);
if (!dev_priv->vram_addr) {
dev_err(dev->dev, "Failure to map stolen base.\n");
ret = -ENOMEM;
......@@ -549,3 +557,31 @@ int psb_gtt_init(struct drm_device *dev, int resume)
psb_gtt_takedown(dev);
return ret;
}
int psb_gtt_restore(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct resource *r = dev_priv->gtt_mem->child;
struct gtt_range *range;
unsigned int restored = 0, total = 0, size = 0;
/* On resume, the gtt_mutex is already initialized */
mutex_lock(&dev_priv->gtt_mutex);
psb_gtt_init(dev, 1);
while (r != NULL) {
range = container_of(r, struct gtt_range, resource);
if (range->pages) {
psb_gtt_insert(dev, range, 1);
size += range->resource.end - range->resource.start;
restored++;
}
r = r->sibling;
total++;
}
mutex_unlock(&dev_priv->gtt_mutex);
DRM_DEBUG_DRIVER("Restored %u of %u gtt ranges (%u KB)", restored,
total, (size / 1024));
return 0;
}
......@@ -60,5 +60,5 @@ extern int psb_gtt_pin(struct gtt_range *gt);
extern void psb_gtt_unpin(struct gtt_range *gt);
extern void psb_gtt_roll(struct drm_device *dev,
struct gtt_range *gt, int roll);
extern int psb_gtt_restore(struct drm_device *dev);
#endif
......@@ -218,12 +218,11 @@ static void parse_backlight_data(struct drm_psb_private *dev_priv,
bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
lvds_bl = kmemdup(vbt_lvds_bl, sizeof(*vbt_lvds_bl), GFP_KERNEL);
if (!lvds_bl) {
dev_err(dev_priv->dev->dev, "out of memory for backlight data\n");
return;
}
memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
dev_priv->lvds_bl = lvds_bl;
}
......
......@@ -19,8 +19,8 @@
*
*/
#ifndef _I830_BIOS_H_
#define _I830_BIOS_H_
#ifndef _INTEL_BIOS_H_
#define _INTEL_BIOS_H_
#include <drm/drmP.h>
#include <drm/drm_dp_helper.h>
......@@ -618,4 +618,4 @@ extern void psb_intel_destroy_bios(struct drm_device *dev);
#define PORT_IDPC 8
#define PORT_IDPD 9
#endif /* _I830_BIOS_H_ */
#endif /* _INTEL_BIOS_H_ */
......@@ -92,8 +92,8 @@ void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
{
struct mdfld_dsi_pkg_sender *sender =
mdfld_dsi_get_pkg_sender(dsi_config);
struct drm_device *dev = sender->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
struct drm_device *dev;
struct drm_psb_private *dev_priv;
u32 gen_ctrl_val;
if (!sender) {
......@@ -101,6 +101,9 @@ void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
return;
}
dev = sender->dev;
dev_priv = dev->dev_private;
/* Set default display backlight value to 85% (0xd8)*/
mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
true);
......
......@@ -110,6 +110,8 @@ static void gma_resume_display(struct pci_dev *pdev)
PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
pci_write_config_word(pdev, PSB_GMCH_CTRL,
dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
psb_gtt_restore(dev); /* Rebuild our GTT mappings */
dev_priv->ops->restore_regs(dev);
}
......@@ -313,3 +315,18 @@ int psb_runtime_idle(struct device *dev)
else
return 1;
}
int gma_power_thaw(struct device *_dev)
{
return gma_power_resume(_dev);
}
int gma_power_freeze(struct device *_dev)
{
return gma_power_suspend(_dev);
}
int gma_power_restore(struct device *_dev)
{
return gma_power_resume(_dev);
}
......@@ -41,6 +41,9 @@ void gma_power_uninit(struct drm_device *dev);
*/
int gma_power_suspend(struct device *dev);
int gma_power_resume(struct device *dev);
int gma_power_thaw(struct device *dev);
int gma_power_freeze(struct device *dev);
int gma_power_restore(struct device *_dev);
/*
* These are the functions the driver should use to wrap all hw access
......
......@@ -601,6 +601,9 @@ static void psb_remove(struct pci_dev *pdev)
static const struct dev_pm_ops psb_pm_ops = {
.resume = gma_power_resume,
.suspend = gma_power_suspend,
.thaw = gma_power_thaw,
.freeze = gma_power_freeze,
.restore = gma_power_restore,
.runtime_suspend = psb_runtime_suspend,
.runtime_resume = psb_runtime_resume,
.runtime_idle = psb_runtime_idle,
......
......@@ -876,7 +876,6 @@ extern const struct psb_ops cdv_chip_ops;
#define PSB_D_MSVDX (1 << 9)
#define PSB_D_TOPAZ (1 << 10)
extern int drm_psb_no_fb;
extern int drm_idle_check_interval;
/*
......
......@@ -50,119 +50,41 @@ struct psb_intel_p2_t {
int p2_slow, p2_fast;
};
#define INTEL_P2_NUM 2
struct psb_intel_limit_t {
struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1;
struct psb_intel_p2_t p2;
};
#define I8XX_DOT_MIN 25000
#define I8XX_DOT_MAX 350000
#define I8XX_VCO_MIN 930000
#define I8XX_VCO_MAX 1400000
#define I8XX_N_MIN 3
#define I8XX_N_MAX 16
#define I8XX_M_MIN 96
#define I8XX_M_MAX 140
#define I8XX_M1_MIN 18
#define I8XX_M1_MAX 26
#define I8XX_M2_MIN 6
#define I8XX_M2_MAX 16
#define I8XX_P_MIN 4
#define I8XX_P_MAX 128
#define I8XX_P1_MIN 2
#define I8XX_P1_MAX 33
#define I8XX_P1_LVDS_MIN 1
#define I8XX_P1_LVDS_MAX 6
#define I8XX_P2_SLOW 4
#define I8XX_P2_FAST 2
#define I8XX_P2_LVDS_SLOW 14
#define I8XX_P2_LVDS_FAST 14 /* No fast option */
#define I8XX_P2_SLOW_LIMIT 165000
#define I9XX_DOT_MIN 20000
#define I9XX_DOT_MAX 400000
#define I9XX_VCO_MIN 1400000
#define I9XX_VCO_MAX 2800000
#define I9XX_N_MIN 1
#define I9XX_N_MAX 6
#define I9XX_M_MIN 70
#define I9XX_M_MAX 120
#define I9XX_M1_MIN 8
#define I9XX_M1_MAX 18
#define I9XX_M2_MIN 3
#define I9XX_M2_MAX 7
#define I9XX_P_SDVO_DAC_MIN 5
#define I9XX_P_SDVO_DAC_MAX 80
#define I9XX_P_LVDS_MIN 7
#define I9XX_P_LVDS_MAX 98
#define I9XX_P1_MIN 1
#define I9XX_P1_MAX 8
#define I9XX_P2_SDVO_DAC_SLOW 10
#define I9XX_P2_SDVO_DAC_FAST 5
#define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000
#define I9XX_P2_LVDS_SLOW 14
#define I9XX_P2_LVDS_FAST 7
#define I9XX_P2_LVDS_SLOW_LIMIT 112000
#define INTEL_LIMIT_I8XX_DVO_DAC 0
#define INTEL_LIMIT_I8XX_LVDS 1
#define INTEL_LIMIT_I9XX_SDVO_DAC 2
#define INTEL_LIMIT_I9XX_LVDS 3
#define INTEL_LIMIT_I9XX_SDVO_DAC 0
#define INTEL_LIMIT_I9XX_LVDS 1
static const struct psb_intel_limit_t psb_intel_limits[] = {
{ /* INTEL_LIMIT_I8XX_DVO_DAC */
.dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
.vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
.n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
.m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
.m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
.m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
.p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
.p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX},
.p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST},
},
{ /* INTEL_LIMIT_I8XX_LVDS */
.dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
.vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
.n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
.m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
.m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
.m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
.p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
.p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX},
.p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST},
},
{ /* INTEL_LIMIT_I9XX_SDVO_DAC */
.dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
.vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
.n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
.m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
.m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
.m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
.p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX},
.p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
.p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast =
I9XX_P2_SDVO_DAC_FAST},
.dot = {.min = 20000, .max = 400000},
.vco = {.min = 1400000, .max = 2800000},
.n = {.min = 1, .max = 6},
.m = {.min = 70, .max = 120},
.m1 = {.min = 8, .max = 18},
.m2 = {.min = 3, .max = 7},
.p = {.min = 5, .max = 80},
.p1 = {.min = 1, .max = 8},
.p2 = {.dot_limit = 200000,
.p2_slow = 10, .p2_fast = 5},
},
{ /* INTEL_LIMIT_I9XX_LVDS */
.dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
.vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
.n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
.m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
.m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
.m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
.p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX},
.p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
.dot = {.min = 20000, .max = 400000},
.vco = {.min = 1400000, .max = 2800000},
.n = {.min = 1, .max = 6},
.m = {.min = 70, .max = 120},
.m1 = {.min = 8, .max = 18},
.m2 = {.min = 3, .max = 7},
.p = {.min = 7, .max = 98},
.p1 = {.min = 1, .max = 8},
/* The single-channel range is 25-112Mhz, and dual-channel
* is 80-224Mhz. Prefer single channel as much as possible.
*/
.p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST},
.p2 = {.dot_limit = 112000,
.p2_slow = 14, .p2_fast = 7},
},
};
......@@ -177,9 +99,7 @@ static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc)
return limit;
}
/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock)
static void psb_intel_clock(int refclk, struct psb_intel_clock_t *clock)
{
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2;
......@@ -187,22 +107,6 @@ static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock)
clock->dot = clock->vco / clock->p;
}
/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock)
{
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2;
clock->vco = refclk * clock->m / (clock->n + 2);
clock->dot = clock->vco / clock->p;
}
static void psb_intel_clock(struct drm_device *dev, int refclk,
struct psb_intel_clock_t *clock)
{
return i9xx_clock(refclk, clock);
}
/**
* Returns whether any output on the specified pipe is of the specified type
*/
......@@ -308,7 +212,7 @@ static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target,
clock.p1++) {
int this_err;
psb_intel_clock(dev, refclk, &clock);
psb_intel_clock(refclk, &clock);
if (!psb_intel_PLL_is_valid
(crtc, &clock))
......@@ -1068,7 +972,7 @@ static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
return 0;
}
void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t type, uint32_t size)
{
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
......@@ -1149,9 +1053,9 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
if ((dpll & PLL_REF_INPUT_MASK) ==
PLLB_REF_INPUT_SPREADSPECTRUMIN) {
/* XXX: might not be 66MHz */
i8xx_clock(66000, &clock);
psb_intel_clock(66000, &clock);
} else
i8xx_clock(48000, &clock);
psb_intel_clock(48000, &clock);
} else {
if (dpll & PLL_P1_DIVIDE_BY_TWO)
clock.p1 = 2;
......@@ -1166,7 +1070,7 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
else
clock.p2 = 2;
i8xx_clock(48000, &clock);
psb_intel_clock(48000, &clock);
}
/* XXX: It would be nice to validate the clocks, but we can't reuse
......@@ -1225,7 +1129,7 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
return mode;
}
void psb_intel_crtc_destroy(struct drm_crtc *crtc)
static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
{
struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
struct gtt_range *gt;
......
......@@ -21,8 +21,5 @@
#define _INTEL_DISPLAY_H_
bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t type, uint32_t size);
void psb_intel_crtc_destroy(struct drm_crtc *crtc);
#endif
......@@ -32,9 +32,6 @@
/* maximum connectors per crtcs in the mode set */
#define INTELFB_CONN_LIMIT 4
#define INTEL_I2C_BUS_DVO 1
#define INTEL_I2C_BUS_SDVO 2
/* Intel Pipe Clone Bit */
#define INTEL_HDMIB_CLONE_BIT 1
#define INTEL_HDMIC_CLONE_BIT 2
......@@ -68,11 +65,6 @@
#define INTEL_OUTPUT_DISPLAYPORT 9
#define INTEL_OUTPUT_EDP 10
#define INTEL_DVO_CHIP_NONE 0
#define INTEL_DVO_CHIP_LVDS 1
#define INTEL_DVO_CHIP_TMDS 2
#define INTEL_DVO_CHIP_TVOUT 4
#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
......
......@@ -493,7 +493,6 @@
#define PIPEACONF_DISABLE 0
#define PIPEACONF_DOUBLE_WIDE (1 << 30)
#define PIPECONF_ACTIVE (1 << 30)
#define I965_PIPECONF_ACTIVE (1 << 30)
#define PIPECONF_DSIPLL_LOCK (1 << 29)
#define PIPEACONF_SINGLE_WIDE 0
#define PIPEACONF_PIPE_UNLOCKED 0
......
......@@ -134,6 +134,9 @@ struct psb_intel_sdvo {
/* Input timings for adjusted_mode */
struct psb_intel_sdvo_dtd input_dtd;
/* Saved SDVO output states */
uint32_t saveSDVO; /* Can be SDVOB or SDVOC depending on sdvo_reg */
};
struct psb_intel_sdvo_connector {
......@@ -1830,6 +1833,34 @@ psb_intel_sdvo_set_property(struct drm_connector *connector,
#undef CHECK_PROPERTY
}
static void psb_intel_sdvo_save(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct psb_intel_encoder *psb_intel_encoder =
psb_intel_attached_encoder(connector);
struct psb_intel_sdvo *sdvo =
to_psb_intel_sdvo(&psb_intel_encoder->base);
sdvo->saveSDVO = REG_READ(sdvo->sdvo_reg);
}
static void psb_intel_sdvo_restore(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct drm_encoder *encoder =
&psb_intel_attached_encoder(connector)->base;
struct psb_intel_sdvo *sdvo = to_psb_intel_sdvo(encoder);
struct drm_crtc *crtc = encoder->crtc;
REG_WRITE(sdvo->sdvo_reg, sdvo->saveSDVO);
/* Force a full mode set on the crtc. We're supposed to have the
mode_config lock already. */
if (connector->status == connector_status_connected)
drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
NULL);
}
static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = {
.dpms = psb_intel_sdvo_dpms,
.mode_fixup = psb_intel_sdvo_mode_fixup,
......@@ -1840,6 +1871,8 @@ static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = {
static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.save = psb_intel_sdvo_save,
.restore = psb_intel_sdvo_restore,
.detect = psb_intel_sdvo_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = psb_intel_sdvo_set_property,
......
......@@ -21,8 +21,8 @@
*
**************************************************************************/
#ifndef _SYSIRQ_H_
#define _SYSIRQ_H_
#ifndef _PSB_IRQ_H_
#define _PSB_IRQ_H_
#include <drm/drmP.h>
......@@ -44,4 +44,4 @@ u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
int mdfld_enable_te(struct drm_device *dev, int pipe);
void mdfld_disable_te(struct drm_device *dev, int pipe);
#endif /* _SYSIRQ_H_ */
#endif /* _PSB_IRQ_H_ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册