[PATCH] drm/fbdev: rework output polling to be back in the core. (v3)
From: Dave Airlie airl...@redhat.com After thinking it over a lot it made more sense for the core to deal with the output polling especially so it can notify X. v2: drop plans for fake connector - per Michel's comments - fix X patch sent to xorg-devel, add intel polled/hpd setting, add initial nouveau polled/hpd settings. v3: add config lock take inside polling, add intel/nouveau poll init/fini calls Signed-off-by: Dave Airlie airl...@redhat.com --- drivers/gpu/drm/Kconfig |2 +- drivers/gpu/drm/drm_crtc_helper.c | 93 drivers/gpu/drm/drm_fb_helper.c | 123 --- drivers/gpu/drm/i915/i915_dma.c |2 +- drivers/gpu/drm/i915/i915_irq.c |3 +- drivers/gpu/drm/i915/intel_crt.c|5 + drivers/gpu/drm/i915/intel_display.c|2 + drivers/gpu/drm/i915/intel_dp.c |2 + drivers/gpu/drm/i915/intel_drv.h|2 +- drivers/gpu/drm/i915/intel_fb.c | 14 ++-- drivers/gpu/drm/i915/intel_hdmi.c |1 + drivers/gpu/drm/i915/intel_sdvo.c |2 + drivers/gpu/drm/nouveau/nouveau_connector.c | 12 +++ drivers/gpu/drm/nouveau/nouveau_display.c |1 + drivers/gpu/drm/nouveau/nouveau_fbcon.c | 14 +-- drivers/gpu/drm/nouveau/nouveau_fbcon.h |2 +- drivers/gpu/drm/nouveau/nouveau_state.c |5 +- drivers/gpu/drm/nouveau/nv50_display.c |2 +- drivers/gpu/drm/radeon/radeon_connectors.c | 13 +++ drivers/gpu/drm/radeon/radeon_display.c | 10 ++ drivers/gpu/drm/radeon/radeon_fb.c | 15 +--- drivers/gpu/drm/radeon/radeon_irq_kms.c |5 +- drivers/gpu/drm/radeon/radeon_mode.h|3 +- include/drm/drm_crtc.h | 17 include/drm/drm_crtc_helper.h |3 + include/drm/drm_fb_helper.h | 13 +--- 26 files changed, 209 insertions(+), 157 deletions(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index be5aa7d..2583ddf 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -9,6 +9,7 @@ menuconfig DRM depends on (AGP || AGP=n) PCI !EMULATED_CMPXCHG MMU select I2C select I2C_ALGOBIT + select SLOW_WORK help Kernel-level support for the Direct Rendering Infrastructure (DRI) introduced in XFree86 4.0. If you say Y here, you need to select @@ -23,7 +24,6 @@ config DRM_KMS_HELPER depends on DRM select FB select FRAMEBUFFER_CONSOLE if !EMBEDDED - select SLOW_WORK help FB and CRTC helpers for KMS drivers. diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index b142ac2..13574b1 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -807,3 +807,96 @@ int drm_helper_resume_force_mode(struct drm_device *dev) return 0; } EXPORT_SYMBOL(drm_helper_resume_force_mode); + +static struct slow_work_ops output_poll_ops; + +#define DRM_OUTPUT_POLL_PERIOD (10*HZ) +static void output_poll_execute(struct slow_work *work) +{ + struct delayed_slow_work *delayed_work = container_of(work, struct delayed_slow_work, work); + struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_slow_work); + struct drm_connector *connector; + enum drm_connector_status old_status, status; + bool repoll = false, changed = false; + int ret; + + mutex_lock(dev-mode_config.mutex); + list_for_each_entry(connector, dev-mode_config.connector_list, head) { + + /* if this is HPD or polled don't check it - + TV out for instance */ + if (!connector-polled) + continue; + + else if (connector-polled (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) + repoll = true; + + old_status = connector-status; + /* if we are connected and don't want to poll for disconnect + skip it */ + if (old_status == connector_status_connected + !(connector-polled DRM_CONNECTOR_POLL_DISCONNECT) + !(connector-polled DRM_CONNECTOR_POLL_HPD)) + continue; + + status = connector-funcs-detect(connector); + if (old_status != status) + changed = true; + } + + if (changed) { + /* send a uevent + call fbdev */ + drm_sysfs_hotplug_event(dev); + if (dev-mode_config.funcs-output_poll_changed) + dev-mode_config.funcs-output_poll_changed(dev); + } + + mutex_unlock(dev-mode_config.mutex); + + if (repoll) { + ret = delayed_slow_work_enqueue(delayed_work, DRM_OUTPUT_POLL_PERIOD); + if (ret) +
Re: [PATCH 09/14] drm/edid: Add test for monitor reduced blanking support.
Adam Jackson wrote: The generic block walk callback looks like overkill, but we'll need it for other detailed block walks in the future. Signed-off-by: Adam Jackson a...@redhat.com --- drivers/gpu/drm/drm_edid.c | 47 --- 1 files changed, 43 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fb7c2fc..ead57ab 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -33,6 +33,10 @@ #include drmP.h #include drm_edid.h +#define EDID_EST_TIMINGS 16 +#define EDID_STD_TIMINGS 8 +#define EDID_DETAILED_TIMINGS 4 + /* * EDID blocks out in the wild have a variety of bugs, try to collect * them here (note that userspace may work around broken monitors first, @@ -673,6 +677,45 @@ static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, return mode; } +typedef void detailed_cb(struct detailed_timing *timing, void *closure); + +static void +drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) +{ + int i; + struct edid *edid = (struct edid *)raw_edid; + + if (edid == NULL) + return; + + for (i = 0; i EDID_DETAILED_TIMINGS; i++) + cb((edid-detailed_timings[i]), closure); + + /* XXX extension block walk */ +} + +static void +is_rb(struct detailed_timing *t, void *data) +{ + u8 *r = (u8 *)t; + if (r[3] == EDID_DETAIL_MONITOR_RANGE) + if (r[15] 0x10) + *(bool *)data = true; +} + +/* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ +static bool +drm_monitor_supports_rb(struct edid *edid) +{ + if (edid-revision = 4) { + bool ret; You need to initialize ret here (bool ret = false;). + drm_for_each_detailed_block((u8 *)edid, is_rb, ret); + return ret; + } + + return ((edid-input DRM_EDID_INPUT_DIGITAL) != 0); +} + /* * 0 is reserved. The spec says 0x01 fill for unused timings. Some old * monitors fill with ascii space (0x20) instead. @@ -964,10 +1007,6 @@ static struct drm_display_mode edid_est_modes[] = { DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x...@75hz */ }; -#define EDID_EST_TIMINGS 16 -#define EDID_STD_TIMINGS 8 -#define EDID_DETAILED_TIMINGS 4 - /** * add_established_modes - get est. modes from EDID and add them * @edid: EDID block to scan MM -- -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
Re: [PATCH] drm/fbdev: rework output polling to be back in the core. (v3)
On Don, 2010-05-06 at 16:15 +1000, Dave Airlie wrote: From: Dave Airlie airl...@redhat.com After thinking it over a lot it made more sense for the core to deal with the output polling especially so it can notify X. v2: drop plans for fake connector - per Michel's comments - fix X patch sent to xorg-devel, add intel polled/hpd setting, add initial nouveau polled/hpd settings. v3: add config lock take inside polling, add intel/nouveau poll init/fini calls Signed-off-by: Dave Airlie airl...@redhat.com Core and radeon parts Reviewed-by: Michel Dänzer mic...@daenzer.net Thanks Dave, looks like the X patch isn't exactly a hard sell either. :) -- Earthling Michel Dänzer |http://www.vmware.com Libre software enthusiast | Debian, X and DRI developer -- -- ___ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel
[PATCH] drm/fbdev: fix cloning on fbcon
From: Dave Airlie airl...@redhat.com Simple cloning rules compared to server: (a) single crtc (b) 1 connector active (c) check command line mode (d) try and find 1024x768 DMT mode if no command line. (e) fail to clone Signed-off-by: Dave Airlie airl...@redhat.com --- drivers/gpu/drm/drm_edid.c | 17 --- drivers/gpu/drm/drm_fb_helper.c | 90 -- include/drm/drm_crtc.h |2 + 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7188674..fe68915 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -658,8 +658,8 @@ static struct drm_display_mode drm_dmt_modes[] = { static const int drm_num_dmt_modes = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); -static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, - int hsize, int vsize, int fresh) +struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, + int hsize, int vsize, int fresh) { int i; struct drm_display_mode *ptr, *mode; @@ -677,6 +677,7 @@ static struct drm_display_mode *drm_find_dmt(struct drm_device *dev, } return mode; } +EXPORT_SYMBOL(drm_mode_find_dmt); typedef void detailed_cb(struct detailed_timing *timing, void *closure); @@ -866,7 +867,7 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid, } /* check whether it can be found in default mode table */ - mode = drm_find_dmt(dev, hsize, vsize, vrefresh_rate); + mode = drm_mode_find_dmt(dev, hsize, vsize, vrefresh_rate); if (mode) return mode; @@ -1386,11 +1387,11 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) if (m num_est3_modes) break; if (est[i] (1 j)) { - mode = drm_find_dmt(connector-dev, - est3_modes[m].w, - est3_modes[m].h, - est3_modes[m].r - /*, est3_modes[m].rb */); + mode = drm_mode_find_dmt(connector-dev, +est3_modes[m].w, +est3_modes[m].h, +est3_modes[m].r +/*, est3_modes[m].rb */); if (mode) { drm_mode_probed_add(connector, mode); modes++; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index d198b82..38728c4 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1070,6 +1070,79 @@ static void drm_enable_connectors(struct drm_fb_helper *fb_helper, } } +static bool drm_target_cloned(struct drm_fb_helper *fb_helper, + struct drm_display_mode **modes, + bool *enabled, int width, int height) +{ + int count, i, j; + bool can_clone = false; + struct drm_fb_helper_connector *fb_helper_conn; + struct drm_display_mode *dmt_mode, *mode; + + /* only contemplate cloning in the single crtc case */ + if (fb_helper-crtc_count 1) + return false; + + count = 0; + for (i = 0; i fb_helper-connector_count; i++) { + if (enabled[i]) + count++; + } + + /* only contemplate cloning if more than one connector is enabled */ + if (count = 1) + return false; + + /* check the command line or if nothing common pick 1024x768 */ + can_clone = true; + for (i = 0; i fb_helper-connector_count; i++) { + if (!enabled[i]) + continue; + fb_helper_conn = fb_helper-connector_info[i]; + modes[i] = drm_pick_cmdline_mode(fb_helper_conn, width, height); + if (!modes[i]) { + can_clone = false; + break; + } + for (j = 0; j i; j++) { + if (!enabled[j]) + continue; + if (!drm_mode_equal(modes[j], modes[i])) + can_clone = false; + } + } + + if (can_clone) { + DRM_DEBUG_KMS(can clone using command line\n); + return true; + } + + /* try and find a 1024x768 mode on each connector */ + can_clone = true; + dmt_mode = drm_mode_find_dmt(fb_helper-dev, 1024, 768,