[PATCH] drm/radeon/kms: clean up multiple crtc handling for evergreen+
On 07/08/2011 09:51 AM, Alex Deucher wrote: > evergreen+ asics have 2-6 crtcs. Don't access crtc registers > for crtc regs that don't exist as they have very high latency > and may cause problems on some asics. The previous code missed > a few cases and was not fine grained enough (missed the 4 crtc > case for example). > > Fixes: > https://bugs.freedesktop.org/show_bug.cgi?id=38800 > > Signed-off-by: Alex Deucher > Reviewed-by: Michel D?nzer > --- > drivers/gpu/drm/radeon/evergreen.c | 159 > ++-- > 1 files changed, 98 insertions(+), 61 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/evergreen.c > b/drivers/gpu/drm/radeon/evergreen.c > index e8a5ffb..bf2493b 100644 > --- a/drivers/gpu/drm/radeon/evergreen.c > +++ b/drivers/gpu/drm/radeon/evergreen.c > @@ -985,17 +985,19 @@ void evergreen_mc_stop(struct radeon_device *rdev, > struct evergreen_mc_save *sav > { > save->vga_control[0] = RREG32(D1VGA_CONTROL); > save->vga_control[1] = RREG32(D2VGA_CONTROL); > - save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); > - save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); > - save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); > - save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); > save->vga_render_control = RREG32(VGA_RENDER_CONTROL); > save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); > save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC0_REGISTER_OFFSET); > save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC1_REGISTER_OFFSET); > - if (!(rdev->flags & RADEON_IS_IGP)) { > + if (rdev->num_crtc >= 4) { > + save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); > + save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); > save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC2_REGISTER_OFFSET); > save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC3_REGISTER_OFFSET); > + } > + if (rdev->num_crtc >= 6) { > + save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); > + save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); > save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC4_REGISTER_OFFSET); > save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC5_REGISTER_OFFSET); > } > @@ -1004,35 +1006,45 @@ void evergreen_mc_stop(struct radeon_device *rdev, > struct evergreen_mc_save *sav > WREG32(VGA_RENDER_CONTROL, 0); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); > - if (!(rdev->flags & RADEON_IS_IGP)) { > + if (rdev->num_crtc >= 4) { > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC2_REGISTER_OFFSET, 1); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC3_REGISTER_OFFSET, 1); > + } > + if (rdev->num_crtc >= 6) { > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC4_REGISTER_OFFSET, 1); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC5_REGISTER_OFFSET, 1); > } > WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); > WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); > - if (!(rdev->flags & RADEON_IS_IGP)) { > + if (rdev->num_crtc >= 4) { > WREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC2_REGISTER_OFFSET, 0); > WREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC3_REGISTER_OFFSET, 0); > + } > + if (rdev->num_crtc >= 6) { > WREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC4_REGISTER_OFFSET, 0); > WREG32(EVERGREEN_CRTC_CONTROL + > EVERGREEN_CRTC5_REGISTER_OFFSET, 0); > } > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); > - if (!(rdev->flags & RADEON_IS_IGP)) { > + if (rdev->num_crtc >= 4) { > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC2_REGISTER_OFFSET, 0); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC3_REGISTER_OFFSET, 0); > + } > + if (rdev->num_crtc >= 6) { > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC4_REGISTER_OFFSET, 0); > WREG32(EVERGREEN_CRTC_UPDATE_LOCK + > EVERGREEN_CRTC5_REGISTER_OFFSET, 0); > } > > WREG32(D1VGA_CONTROL, 0); > WREG32(D2VGA_CONTROL, 0); > - WREG32(EVERGREEN_D3VGA_CONTROL, 0); > - WREG32(EVERGREEN_D4VGA_CONTROL, 0); > - WREG32(EVERGREEN_D5VGA_CONTROL, 0); > - WREG32(EVERGREEN_D6VGA_CONTROL, 0); > + if (rdev->num_crtc >= 4) { > + WREG32(EVERGREEN_D3VGA_CONTROL, 0); > + WREG32(EVERGREEN_D4VGA_CONTROL, 0); > + } > + if
Re: [PATCH] drm/radeon/kms: clean up multiple crtc handling for evergreen+
On 07/08/2011 09:51 AM, Alex Deucher wrote: evergreen+ asics have 2-6 crtcs. Don't access crtc registers for crtc regs that don't exist as they have very high latency and may cause problems on some asics. The previous code missed a few cases and was not fine grained enough (missed the 4 crtc case for example). Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=38800 Signed-off-by: Alex Deucher alexdeuc...@gmail.com Reviewed-by: Michel Dänzer mic...@daenzer.net --- drivers/gpu/drm/radeon/evergreen.c | 159 ++-- 1 files changed, 98 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e8a5ffb..bf2493b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -985,17 +985,19 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav { save-vga_control[0] = RREG32(D1VGA_CONTROL); save-vga_control[1] = RREG32(D2VGA_CONTROL); - save-vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); - save-vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); - save-vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); - save-vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); save-vga_render_control = RREG32(VGA_RENDER_CONTROL); save-vga_hdp_control = RREG32(VGA_HDP_CONTROL); save-crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); save-crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (!(rdev-flags RADEON_IS_IGP)) { + if (rdev-num_crtc = 4) { + save-vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); + save-vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); save-crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); save-crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev-num_crtc = 6) { + save-vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); + save-vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); save-crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); save-crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); } @@ -1004,35 +1006,45 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav WREG32(VGA_RENDER_CONTROL, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (!(rdev-flags RADEON_IS_IGP)) { + if (rdev-num_crtc = 4) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); + } + if (rdev-num_crtc = 6) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); } WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev-flags RADEON_IS_IGP)) { + if (rdev-num_crtc = 4) { WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev-num_crtc = 6) { WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (!(rdev-flags RADEON_IS_IGP)) { + if (rdev-num_crtc = 4) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + } + if (rdev-num_crtc = 6) { WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); } WREG32(D1VGA_CONTROL, 0); WREG32(D2VGA_CONTROL, 0); - WREG32(EVERGREEN_D3VGA_CONTROL, 0); - WREG32(EVERGREEN_D4VGA_CONTROL, 0); - WREG32(EVERGREEN_D5VGA_CONTROL, 0); - WREG32(EVERGREEN_D6VGA_CONTROL, 0); + if (rdev-num_crtc = 4) { + WREG32(EVERGREEN_D3VGA_CONTROL, 0); + WREG32(EVERGREEN_D4VGA_CONTROL, 0); + } + if (rdev-num_crtc = 6) { + WREG32(EVERGREEN_D5VGA_CONTROL, 0); + WREG32(EVERGREEN_D6VGA_CONTROL,
Re: [RFC] drm: emit change events when mode config changes
On 04/14/2011 12:42 PM, Jesse Barnes wrote: We've already seen that apps want to monitor the display config, and some (like upowerd) poll for changes since we don't provide a notification for general mode config changes, just hotplug events. So add a new drm event, with CHANGE=1 set in the event, to allow for it. Signed-off-by: Jesse Barnes jbar...@virtuousgeek.org diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4c95b5f..174ee64 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1589,6 +1589,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, set.fb = fb; ret = crtc-funcs-set_config(set); + drm_sysfs_change_event(dev); + out: kfree(connector_set); mutex_unlock(dev-mode_config.mutex); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 9507204..df946d4 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -822,6 +822,8 @@ int drm_fb_helper_set_par(struct fb_info *info) return ret; } } + + drm_sysfs_change_event(dev); mutex_unlock(dev-mode_config.mutex); if (fb_helper-delayed_hotplug) { diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 2eee8e0..fd3af31 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -467,9 +467,9 @@ EXPORT_SYMBOL(drm_sysfs_connector_remove); * drm_sysfs_hotplug_event - generate a DRM uevent * @dev: DRM device * - * Send a uevent for the DRM device specified by @dev. Currently we only - * set HOTPLUG=1 in the uevent environment, but this could be expanded to - * deal with other types of events. + * Send a uevent for the DRM device specified by @dev. Set HOTPLUG=1 in the + * event to indicate a display config change occurred, probably due to a + * display being added or removed. */ void drm_sysfs_hotplug_event(struct drm_device *dev) { @@ -483,6 +483,24 @@ void drm_sysfs_hotplug_event(struct drm_device *dev) EXPORT_SYMBOL(drm_sysfs_hotplug_event); /** + * drm_sysfs_change_event - generate a DRM uevent indicating a display config change + * @dev: DRM device + * + * Send a uevent for the DRM device specified by @dev. Set CHANGE=1 to + * indicate that a userspace initiated display configuration change occurred. + */ +void drm_sysfs_change_event(struct drm_device *dev) +{ + char *event_string = CHANGE=1; + char *envp[] = { event_string, NULL }; + + DRM_DEBUG(generating hotplug event\n); Should be change event here? + + kobject_uevent_env(dev-primary-kdev.kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(drm_sysfs_change_event); + +/** * drm_sysfs_device_add - adds a class device to sysfs for a character driver * @dev: DRM device to be added * @head: DRM head in question diff --git a/include/drm/drmP.h b/include/drm/drmP.h index ad5770f..3aff8fc 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1506,6 +1506,7 @@ extern struct class *drm_sysfs_create(struct module *owner, char *name); extern void drm_sysfs_destroy(void); extern int drm_sysfs_device_add(struct drm_minor *minor); extern void drm_sysfs_hotplug_event(struct drm_device *dev); +extern void drm_sysfs_change_event(struct drm_device *dev); extern void drm_sysfs_device_remove(struct drm_minor *minor); extern char *drm_get_connector_status_name(enum drm_connector_status status); extern int drm_sysfs_connector_add(struct drm_connector *connector); -- Benefiting from Server Virtualization: Beyond Initial Workload Consolidation -- Increasing the use of server virtualization is a top priority.Virtualization can reduce costs, simplify management, and improve application availability and disaster protection. Learn more about boosting the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev -- ___ Dri-devel mailing list dri-de...@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Benefiting from Server Virtualization: Beyond Initial Workload Consolidation -- Increasing the use of server virtualization is a top priority.Virtualization can reduce costs, simplify management, and improve application availability and disaster protection. Learn more about boosting the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev -- ___ Dri-devel mailing list dri-de...@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
[RFC] drm: emit change events when mode config changes
On 04/14/2011 12:42 PM, Jesse Barnes wrote: > We've already seen that apps want to monitor the display config, and > some (like upowerd) poll for changes since we don't provide a > notification for general mode config changes, just hotplug events. So > add a new drm event, with CHANGE=1 set in the event, to allow for it. > > Signed-off-by: Jesse Barnes > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 4c95b5f..174ee64 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -1589,6 +1589,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, > set.fb = fb; > ret = crtc->funcs->set_config(); > > + drm_sysfs_change_event(dev); > + > out: > kfree(connector_set); > mutex_unlock(>mode_config.mutex); > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c > index 9507204..df946d4 100644 > --- a/drivers/gpu/drm/drm_fb_helper.c > +++ b/drivers/gpu/drm/drm_fb_helper.c > @@ -822,6 +822,8 @@ int drm_fb_helper_set_par(struct fb_info *info) > return ret; > } > } > + > + drm_sysfs_change_event(dev); > mutex_unlock(>mode_config.mutex); > > if (fb_helper->delayed_hotplug) { > diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c > index 2eee8e0..fd3af31 100644 > --- a/drivers/gpu/drm/drm_sysfs.c > +++ b/drivers/gpu/drm/drm_sysfs.c > @@ -467,9 +467,9 @@ EXPORT_SYMBOL(drm_sysfs_connector_remove); > * drm_sysfs_hotplug_event - generate a DRM uevent > * @dev: DRM device > * > - * Send a uevent for the DRM device specified by @dev. Currently we only > - * set HOTPLUG=1 in the uevent environment, but this could be expanded to > - * deal with other types of events. > + * Send a uevent for the DRM device specified by @dev. Set HOTPLUG=1 in the > + * event to indicate a display config change occurred, probably due to a > + * display being added or removed. > */ > void drm_sysfs_hotplug_event(struct drm_device *dev) > { > @@ -483,6 +483,24 @@ void drm_sysfs_hotplug_event(struct drm_device *dev) > EXPORT_SYMBOL(drm_sysfs_hotplug_event); > > /** > + * drm_sysfs_change_event - generate a DRM uevent indicating a display > config change > + * @dev: DRM device > + * > + * Send a uevent for the DRM device specified by @dev. Set CHANGE=1 to > + * indicate that a userspace initiated display configuration change occurred. > + */ > +void drm_sysfs_change_event(struct drm_device *dev) > +{ > + char *event_string = "CHANGE=1"; > + char *envp[] = { event_string, NULL }; > + > + DRM_DEBUG("generating hotplug event\n"); Should be "change event" here? > + > + kobject_uevent_env(>primary->kdev.kobj, KOBJ_CHANGE, envp); > +} > +EXPORT_SYMBOL(drm_sysfs_change_event); > + > +/** > * drm_sysfs_device_add - adds a class device to sysfs for a character driver > * @dev: DRM device to be added > * @head: DRM head in question > diff --git a/include/drm/drmP.h b/include/drm/drmP.h > index ad5770f..3aff8fc 100644 > --- a/include/drm/drmP.h > +++ b/include/drm/drmP.h > @@ -1506,6 +1506,7 @@ extern struct class *drm_sysfs_create(struct module > *owner, char *name); > extern void drm_sysfs_destroy(void); > extern int drm_sysfs_device_add(struct drm_minor *minor); > extern void drm_sysfs_hotplug_event(struct drm_device *dev); > +extern void drm_sysfs_change_event(struct drm_device *dev); > extern void drm_sysfs_device_remove(struct drm_minor *minor); > extern char *drm_get_connector_status_name(enum drm_connector_status status); > extern int drm_sysfs_connector_add(struct drm_connector *connector); > > -- > Benefiting from Server Virtualization: Beyond Initial Workload > Consolidation -- Increasing the use of server virtualization is a top > priority.Virtualization can reduce costs, simplify management, and improve > application availability and disaster protection. Learn more about boosting > the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev > -- > ___ > Dri-devel mailing list > Dri-devel at lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/dri-devel > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Benefiting from Server Virtualization: Beyond Initial Workload Consolidation -- Increasing the use of server virtualization is a top priority.Virtualization can reduce costs, simplify management, and improve application availability and disaster protection. Learn more about boosting the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev -- ___ Dri-devel mailing list Dri-devel at lists.sourceforge.net