diff options
Diffstat (limited to 'drivers/gpu/drm/gma500/psb_device.c')
| -rw-r--r-- | drivers/gpu/drm/gma500/psb_device.c | 156 |
1 files changed, 94 insertions, 62 deletions
diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index e5f5906172b..07df7d4eea7 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -20,12 +20,13 @@ #include <linux/backlight.h> #include <drm/drmP.h> #include <drm/drm.h> -#include "gma_drm.h" +#include <drm/gma_drm.h> #include "psb_drv.h" #include "psb_reg.h" #include "psb_intel_reg.h" #include "intel_bios.h" - +#include "psb_device.h" +#include "gma_device.h" static int psb_output_init(struct drm_device *dev) { @@ -144,6 +145,10 @@ static int psb_backlight_init(struct drm_device *dev) psb_backlight_device->props.max_brightness = 100; backlight_update_status(psb_backlight_device); dev_priv->backlight_device = psb_backlight_device; + + /* This must occur after the backlight is properly initialised */ + psb_lid_timer_init(dev_priv); + return 0; } @@ -177,28 +182,30 @@ static int psb_save_display_registers(struct drm_device *dev) struct drm_psb_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; struct drm_connector *connector; + struct psb_state *regs = &dev_priv->regs.psb; /* Display arbitration control + watermarks */ - dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); - dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); - dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); - dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); - dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); - dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); - dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); - dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); + regs->saveDSPARB = PSB_RVDC32(DSPARB); + regs->saveDSPFW1 = PSB_RVDC32(DSPFW1); + regs->saveDSPFW2 = PSB_RVDC32(DSPFW2); + regs->saveDSPFW3 = PSB_RVDC32(DSPFW3); + regs->saveDSPFW4 = PSB_RVDC32(DSPFW4); + regs->saveDSPFW5 = PSB_RVDC32(DSPFW5); + regs->saveDSPFW6 = PSB_RVDC32(DSPFW6); + regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); /* Save crtc and output state */ - mutex_lock(&dev->mode_config.mutex); + drm_modeset_lock_all(dev); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (drm_helper_crtc_in_use(crtc)) crtc->funcs->save(crtc); } list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->save(connector); + if (connector->funcs->save) + connector->funcs->save(connector); - mutex_unlock(&dev->mode_config.mutex); + drm_modeset_unlock_all(dev); return 0; } @@ -213,29 +220,31 @@ static int psb_restore_display_registers(struct drm_device *dev) struct drm_psb_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; struct drm_connector *connector; + struct psb_state *regs = &dev_priv->regs.psb; /* Display arbitration + watermarks */ - PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); - PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); - PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); - PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); - PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); - PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); - PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); - PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); + PSB_WVDC32(regs->saveDSPARB, DSPARB); + PSB_WVDC32(regs->saveDSPFW1, DSPFW1); + PSB_WVDC32(regs->saveDSPFW2, DSPFW2); + PSB_WVDC32(regs->saveDSPFW3, DSPFW3); + PSB_WVDC32(regs->saveDSPFW4, DSPFW4); + PSB_WVDC32(regs->saveDSPFW5, DSPFW5); + PSB_WVDC32(regs->saveDSPFW6, DSPFW6); + PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT); /*make sure VGA plane is off. it initializes to on after reset!*/ PSB_WVDC32(0x80000000, VGACNTRL); - mutex_lock(&dev->mode_config.mutex); + drm_modeset_lock_all(dev); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) if (drm_helper_crtc_in_use(crtc)) crtc->funcs->restore(crtc); list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->restore(connector); + if (connector->funcs->restore) + connector->funcs->restore(connector); - mutex_unlock(&dev->mode_config.mutex); + drm_modeset_unlock_all(dev); return 0; } @@ -249,55 +258,73 @@ static int psb_power_up(struct drm_device *dev) return 0; } -static void psb_get_core_freq(struct drm_device *dev) -{ - uint32_t clock; - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); - struct drm_psb_private *dev_priv = dev->dev_private; - - /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ - /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ - - pci_write_config_dword(pci_root, 0xD0, 0xD0050300); - pci_read_config_dword(pci_root, 0xD4, &clock); - pci_dev_put(pci_root); - - switch (clock & 0x07) { - case 0: - dev_priv->core_freq = 100; - break; - case 1: - dev_priv->core_freq = 133; - break; - case 2: - dev_priv->core_freq = 150; - break; - case 3: - dev_priv->core_freq = 178; - break; - case 4: - dev_priv->core_freq = 200; - break; - case 5: - case 6: - case 7: - dev_priv->core_freq = 266; - default: - dev_priv->core_freq = 0; +/* Poulsbo */ +static const struct psb_offset psb_regmap[2] = { + { + .fp0 = FPA0, + .fp1 = FPA1, + .cntr = DSPACNTR, + .conf = PIPEACONF, + .src = PIPEASRC, + .dpll = DPLL_A, + .htotal = HTOTAL_A, + .hblank = HBLANK_A, + .hsync = HSYNC_A, + .vtotal = VTOTAL_A, + .vblank = VBLANK_A, + .vsync = VSYNC_A, + .stride = DSPASTRIDE, + .size = DSPASIZE, + .pos = DSPAPOS, + .base = DSPABASE, + .surf = DSPASURF, + .addr = DSPABASE, + .status = PIPEASTAT, + .linoff = DSPALINOFF, + .tileoff = DSPATILEOFF, + .palette = PALETTE_A, + }, + { + .fp0 = FPB0, + .fp1 = FPB1, + .cntr = DSPBCNTR, + .conf = PIPEBCONF, + .src = PIPEBSRC, + .dpll = DPLL_B, + .htotal = HTOTAL_B, + .hblank = HBLANK_B, + .hsync = HSYNC_B, + .vtotal = VTOTAL_B, + .vblank = VBLANK_B, + .vsync = VSYNC_B, + .stride = DSPBSTRIDE, + .size = DSPBSIZE, + .pos = DSPBPOS, + .base = DSPBBASE, + .surf = DSPBSURF, + .addr = DSPBBASE, + .status = PIPEBSTAT, + .linoff = DSPBLINOFF, + .tileoff = DSPBTILEOFF, + .palette = PALETTE_B, } -} +}; static int psb_chip_setup(struct drm_device *dev) { - psb_get_core_freq(dev); + struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->regmap = psb_regmap; + gma_get_core_freq(dev); gma_intel_setup_gmbus(dev); - gma_intel_opregion_init(dev); + psb_intel_opregion_init(dev); psb_intel_init_bios(dev); return 0; } static void psb_chip_teardown(struct drm_device *dev) { + struct drm_psb_private *dev_priv = dev->dev_private; + psb_lid_timer_takedown(dev_priv); gma_intel_teardown_gmbus(dev); } @@ -306,12 +333,17 @@ const struct psb_ops psb_chip_ops = { .accel_2d = 1, .pipes = 2, .crtcs = 2, + .hdmi_mask = (1 << 0), + .lvds_mask = (1 << 1), + .sdvo_mask = (1 << 0), + .cursor_needs_phys = 1, .sgx_offset = PSB_SGX_OFFSET, .chip_setup = psb_chip_setup, .chip_teardown = psb_chip_teardown, .crtc_helper = &psb_intel_helper_funcs, .crtc_funcs = &psb_intel_crtc_funcs, + .clock_funcs = &psb_clock_funcs, .output_init = psb_output_init, |
