From: <mad...@ke...> - 2008-06-27 16:45:41
|
libdrm/xf86drmMode.c | 2 - linux-core/drm_crtc.c | 6 ++- linux-core/nv50_dac.c | 38 ++++++++++++++++++++++++ linux-core/nv50_kms_wrapper.c | 65 +++++++++++++++++++++++++++++++++++++----- linux-core/nv50_output.h | 2 + linux-core/nv50_sor.c | 24 +++++++++++++++ 6 files changed, 127 insertions(+), 10 deletions(-) New commits: commit 9f28da80f6cc8e45670b217a2483983f2838095d Author: Maarten Maathuis <mad...@gm...> Date: Fri Jun 27 18:45:08 2008 +0200 Change some obviously wrong things about property blobs, still broken though. - I do not fully understand these blobs, so i'm leaving it at this for the moment. diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c index df86541..ca21a96 100644 --- a/libdrm/xf86drmMode.c +++ b/libdrm/xf86drmMode.c @@ -495,7 +495,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id) if (prop.flags & DRM_MODE_PROP_ENUM) { r->count_enums = prop.count_enum_blobs; r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum)); - } else if (prop.flags & DRM_MODE_PROP_ENUM) { + } else if (prop.flags & DRM_MODE_PROP_BLOB) { r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t)); r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t)); r->count_blobs = prop.count_enum_blobs; diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index b9276c3..23ae7d8 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -1837,7 +1837,6 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, out_resp->count_values = value_count; if (property->flags & DRM_MODE_PROP_ENUM) { - if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { copied = 0; enum_ptr = (struct drm_mode_property_enum *)(unsigned long)out_resp->enum_blob_ptr; @@ -1879,7 +1878,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, copied++; } } - out_resp->count_enum_blobs = enum_count; + out_resp->count_enum_blobs = blob_count; } done: mutex_unlock(&dev->mode_config.mutex); commit 71906e86e81440037aa08b6f23f36e9fd3835639 Author: Maarten Maathuis <mad...@gm...> Date: Fri Jun 27 16:30:25 2008 +0200 [modesetting-101] Actually store properties when being changed. diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c index 4f21d09..b9276c3 100644 --- a/linux-core/drm_crtc.c +++ b/linux-core/drm_crtc.c @@ -2017,6 +2017,9 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, } } + /* store the property value */ + drm_connector_property_set_value(connector, property, out_resp->value); + if (connector->funcs->set_property) ret = connector->funcs->set_property(connector, property, out_resp->value); diff --git a/linux-core/nv50_kms_wrapper.c b/linux-core/nv50_kms_wrapper.c index 900dfcc..9ece228 100644 --- a/linux-core/nv50_kms_wrapper.c +++ b/linux-core/nv50_kms_wrapper.c @@ -663,6 +663,23 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) goto out; } } + + /* update dpms state to DPMSModeOn */ + for (i = 0; i < set->num_connectors; i++) { + drm_connector = set->connectors[i]; + if (!drm_connector) { + DRM_ERROR("No connector\n"); + goto out; + } + + rval = drm_connector_property_set_value(drm_connector, + dev->mode_config.dpms_property, + DPMSModeOn); + if (rval != 0) { + DRM_ERROR("failed to update dpms state\n"); + goto out; + } + } } display->update(display); commit 01ee5eda9aaff880153223df8bb70a34b1a87cee Author: Maarten Maathuis <mad...@gm...> Date: Fri Jun 27 01:29:30 2008 +0200 NV50: A minor change. diff --git a/linux-core/nv50_kms_wrapper.c b/linux-core/nv50_kms_wrapper.c index 79eb296..900dfcc 100644 --- a/linux-core/nv50_kms_wrapper.c +++ b/linux-core/nv50_kms_wrapper.c @@ -484,6 +484,8 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) */ if (switch_fb) { + crtc = to_nv50_crtc(set->crtc); + /* set framebuffer */ set->crtc->fb = set->fb; @@ -573,6 +575,8 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) */ if (modeset) { + crtc = to_nv50_crtc(set->crtc); + /* disconnect unused outputs */ list_for_each_entry(output, &display->outputs, head) { if (output->crtc) { @@ -586,6 +590,14 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) } } + /* blank any unused crtcs */ + list_for_each_entry(crtc, &display->crtcs, head) { + if (!(crtc_mask & (1 << crtc->index))) + crtc->blank(crtc, TRUE); + } + + crtc = to_nv50_crtc(set->crtc); + rval = crtc->set_mode(crtc, hw_mode); if (rval != 0) { DRM_ERROR("crtc mode set failed\n"); @@ -651,12 +663,6 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) goto out; } } - - /* blank any unused crtcs */ - list_for_each_entry(crtc, &display->crtcs, head) { - if (!(crtc_mask & (1 << crtc->index))) - crtc->blank(crtc, TRUE); - } } display->update(display); commit 701011224c048e064295ee12e8a02f7f66d4175a Author: Maarten Maathuis <mad...@gm...> Date: Fri Jun 27 01:16:36 2008 +0200 NV50: Implement DPMS. diff --git a/linux-core/nv50_dac.c b/linux-core/nv50_dac.c index b237241..f51ecf9 100644 --- a/linux-core/nv50_dac.c +++ b/linux-core/nv50_dac.c @@ -96,6 +96,43 @@ static int nv50_dac_set_clock_mode(struct nv50_output *output) return 0; } +static int nv50_dac_set_power_mode(struct nv50_output *output, int mode) +{ + struct drm_nouveau_private *dev_priv = output->dev->dev_private; + uint32_t val; + int or = nv50_output_or_offset(output); + + NV50_DEBUG("or %d\n", or); + + /* wait for it to be done */ + while (NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); + + val = NV_READ(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or)) & ~0x7F; + + if (mode != DPMSModeOn) + val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_BLANKED; + + switch (mode) { + case DPMSModeStandby: + val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF; + break; + case DPMSModeSuspend: + val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF; + break; + case DPMSModeOff: + val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_OFF; + val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF; + val |= NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF; + break; + default: + break; + } + + NV_WRITE(NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(or), val | NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING); + + return 0; +} + static int nv50_dac_destroy(struct nv50_output *output) { struct drm_device *dev = output->dev; @@ -172,6 +209,7 @@ int nv50_dac_create(struct drm_device *dev, int dcb_entry) output->validate_mode = nv50_dac_validate_mode; output->execute_mode = nv50_dac_execute_mode; output->set_clock_mode = nv50_dac_set_clock_mode; + output->set_power_mode = nv50_dac_set_power_mode; output->detect = NULL; /* TODO */ output->destroy = nv50_dac_destroy; diff --git a/linux-core/nv50_kms_wrapper.c b/linux-core/nv50_kms_wrapper.c index 8b97882..79eb296 100644 --- a/linux-core/nv50_kms_wrapper.c +++ b/linux-core/nv50_kms_wrapper.c @@ -640,6 +640,18 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) /* next line changes crtc, so putting it here is important */ display->last_crtc = crtc->index; + /* this is executed immediately */ + list_for_each_entry(output, &display->outputs, head) { + if (output->crtc != crtc) + continue; + + rval = output->set_power_mode(output, DPMSModeOn); + if (rval != 0) { + DRM_ERROR("output set power mode failed\n"); + goto out; + } + } + /* blank any unused crtcs */ list_for_each_entry(crtc, &display->crtcs, head) { if (!(crtc_mask & (1 << crtc->index))) @@ -654,9 +666,6 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set) return 0; out: - if (display) - display->update(display); - kfree(hw_mode); if (rval != 0) @@ -938,12 +947,31 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u } } +static bool nv50_kms_connector_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t value) +{ + struct drm_device *dev = connector->dev; + + if (property == dev->mode_config.dpms_property && connector->encoder) { + struct nv50_output *output = to_nv50_output(connector->encoder); + + if (!output->set_power_mode(output, (int) value)) + return true; + else + return false; + } + + return false; +} + static const struct drm_connector_funcs nv50_kms_connector_funcs = { .save = NULL, .restore = NULL, .detect = nv50_kms_connector_detect, .destroy = nv50_kms_connector_destroy, .fill_modes = nv50_kms_connector_fill_modes, + .set_property = nv50_kms_connector_set_property }; static int nv50_kms_connectors_init(struct drm_device *dev) diff --git a/linux-core/nv50_output.h b/linux-core/nv50_output.h index bdee282..7a6f9c7 100644 --- a/linux-core/nv50_output.h +++ b/linux-core/nv50_output.h @@ -49,6 +49,8 @@ struct nv50_output { int (*validate_mode) (struct nv50_output *output, struct nouveau_hw_mode *mode); int (*execute_mode) (struct nv50_output *output, bool disconnect); int (*set_clock_mode) (struct nv50_output *output); + /* this is not a normal modeset call, it is a direct register write, so it's executed immediately */ + int (*set_power_mode) (struct nv50_output *output, int mode); bool (*detect) (struct nv50_output *output); int (*destroy) (struct nv50_output *output); }; diff --git a/linux-core/nv50_sor.c b/linux-core/nv50_sor.c index fca9612..8419280 100644 --- a/linux-core/nv50_sor.c +++ b/linux-core/nv50_sor.c @@ -114,6 +114,29 @@ static int nv50_sor_set_clock_mode(struct nv50_output *output) return 0; } +static int nv50_sor_set_power_mode(struct nv50_output *output, int mode) +{ + struct drm_nouveau_private *dev_priv = output->dev->dev_private; + uint32_t val; + int or = nv50_output_or_offset(output); + + NV50_DEBUG("or %d\n", nv50_output_or_offset(output)); + + /* wait for it to be done */ + while (NV_READ(NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(or)) & NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_PENDING); + + val = NV_READ(NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(or)); + + if (mode == DPMSModeOn) + val |= NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_ON; + else + val &= ~NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_ON; + + NV_WRITE(NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(or), val | NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_PENDING); + + return 0; +} + static int nv50_sor_destroy(struct nv50_output *output) { struct drm_device *dev = output->dev; @@ -194,6 +217,7 @@ int nv50_sor_create(struct drm_device *dev, int dcb_entry) output->validate_mode = nv50_sor_validate_mode; output->execute_mode = nv50_sor_execute_mode; output->set_clock_mode = nv50_sor_set_clock_mode; + output->set_power_mode = nv50_sor_set_power_mode; output->detect = NULL; output->destroy = nv50_sor_destroy; |