From 3b11228b54cc6bda4a72bb22984203c6eff4338a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 15 Apr 2011 12:49:23 -0700 Subject: drm: add bit depth parsing EDID 1.4 digital monitors report the bit depth supported in the input field. Add support for parsing this out and storing the info in the display_info structure for use by drivers. [airlied: tweaked to fix inter-patch dependency] Signed-off-by: Jesse Barnes Reviewed-by: Adam Jackson Signed-off-by: Dave Airlie --- include/drm/drm_crtc.h | 1 + include/drm/drm_edid.h | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d94684b7ba3..ee1cb7012e5 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -198,6 +198,7 @@ struct drm_display_info { unsigned int min_vfreq, max_vfreq; unsigned int min_hfreq, max_hfreq; unsigned int pixel_clock; + unsigned int bpc; enum subpixel_order subpixel_order; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 5881fad91fa..9b9bf946a20 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -155,7 +155,22 @@ struct detailed_timing { #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3) #define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4) #define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5) -#define DRM_EDID_INPUT_DIGITAL (1 << 7) /* bits below must be zero if set */ +#define DRM_EDID_INPUT_DIGITAL (1 << 7) +#define DRM_EDID_DIGITAL_DEPTH_MASK (7 << 4) +#define DRM_EDID_DIGITAL_DEPTH_UNDEF (0 << 4) +#define DRM_EDID_DIGITAL_DEPTH_6 (1 << 4) +#define DRM_EDID_DIGITAL_DEPTH_8 (2 << 4) +#define DRM_EDID_DIGITAL_DEPTH_10 (3 << 4) +#define DRM_EDID_DIGITAL_DEPTH_12 (4 << 4) +#define DRM_EDID_DIGITAL_DEPTH_14 (5 << 4) +#define DRM_EDID_DIGITAL_DEPTH_16 (6 << 4) +#define DRM_EDID_DIGITAL_DEPTH_RSVD (7 << 4) +#define DRM_EDID_DIGITAL_TYPE_UNDEF (0) +#define DRM_EDID_DIGITAL_TYPE_DVI (1) +#define DRM_EDID_DIGITAL_TYPE_HDMI_A (2) +#define DRM_EDID_DIGITAL_TYPE_HDMI_B (3) +#define DRM_EDID_DIGITAL_TYPE_MDDI (4) +#define DRM_EDID_DIGITAL_TYPE_DP (5) #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0) #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1) -- cgit v1.2.3 From da05a5a71ad8fc7c51d526151be193b7ef6e6c95 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 15 Apr 2011 13:48:57 -0700 Subject: drm: parse color format support for digital displays EDID 1.4 digital displays report the color spaces they support in the features block. Add support for grabbing this data and stuffing it into the display_info struct for driver use. Signed-off-by: Jesse Barnes Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 7 +++++++ include/drm/drm_crtc.h | 5 ++++- include/drm/drm_edid.h | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fe0d3dcd4d3..0a9357c66ff 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1429,6 +1429,7 @@ static void drm_add_display_info(struct edid *edid, /* driver figures it out in this case */ info->bpc = 0; + info->color_formats = 0; /* Only defined for 1.4 with digital displays */ if (edid->revision < 4) @@ -1461,6 +1462,12 @@ static void drm_add_display_info(struct edid *edid, info->bpc = 0; break; } + + info->color_formats = DRM_COLOR_FORMAT_RGB444; + if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB444) + info->color_formats = DRM_COLOR_FORMAT_YCRCB444; + if (info->color_formats & DRM_EDID_FEATURE_RGB_YCRCB422) + info->color_formats = DRM_COLOR_FORMAT_YCRCB422; } /** diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index ee1cb7012e5..9573e0ce312 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -183,7 +183,9 @@ enum subpixel_order { SubPixelNone, }; - +#define DRM_COLOR_FORMAT_RGB444 (1<<0) +#define DRM_COLOR_FORMAT_YCRCB444 (1<<1) +#define DRM_COLOR_FORMAT_YCRCB422 (1<<2) /* * Describes a given display (e.g. CRT or flat panel) and its limitations. */ @@ -201,6 +203,7 @@ struct drm_display_info { unsigned int bpc; enum subpixel_order subpixel_order; + u32 color_formats; char *raw_edid; /* if any */ }; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 9b9bf946a20..eacb415b309 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -175,7 +175,15 @@ struct detailed_timing { #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0) #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1) #define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2) +/* If analog */ #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ +/* If digital */ +#define DRM_EDID_FEATURE_COLOR_MASK (3 << 3) +#define DRM_EDID_FEATURE_RGB (0 << 3) +#define DRM_EDID_FEATURE_RGB_YCRCB444 (1 << 3) +#define DRM_EDID_FEATURE_RGB_YCRCB422 (2 << 3) +#define DRM_EDID_FEATURE_RGB_YCRCB (3 << 3) /* both 4:4:4 and 4:2:2 */ + #define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 5) #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6) #define DRM_EDID_FEATURE_PM_STANDBY (1 << 7) -- cgit v1.2.3 From 7394371d85699a1d6d49b61f65583d6cd902a6a2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 22 Apr 2011 11:03:57 +0100 Subject: drm: Take lock around probes for drm_fb_helper_hotplug_event We need to hold the dev->mode_config.mutex whilst detecting the output status. But we also need to drop it for the call into drm_fb_helper_single_fb_probe(), which indirectly acquires the lock when attaching the fbcon. Failure to do so exposes a race with normal output probing. Detected by adding some warnings that the mutex is held to the backend detect routines: [ 17.772456] WARNING: at drivers/gpu/drm/i915/intel_crt.c:471 intel_crt_detect+0x3e/0x373 [i915]() [ 17.772458] Hardware name: Latitude E6400 [ 17.772460] Modules linked in: .... [ 17.772582] Pid: 11, comm: kworker/0:1 Tainted: G W 2.6.38.4-custom.2 #8 [ 17.772584] Call Trace: [ 17.772591] [] ? warn_slowpath_common+0x78/0x8c [ 17.772603] [] ? intel_crt_detect+0x3e/0x373 [i915] [ 17.772612] [] ? drm_helper_probe_single_connector_modes+0xbf/0x2af [drm_kms_helper] [ 17.772619] [] ? drm_fb_helper_probe_connector_modes+0x39/0x4d [drm_kms_helper] [ 17.772625] [] ? drm_fb_helper_hotplug_event+0xa5/0xc3 [drm_kms_helper] [ 17.772633] [] ? output_poll_execute+0x146/0x17c [drm_kms_helper] [ 17.772638] [] ? cfq_init_queue+0x247/0x345 [ 17.772644] [] ? output_poll_execute+0x0/0x17c [drm_kms_helper] [ 17.772648] [] ? process_one_work+0x193/0x28e [ 17.772652] [] ? worker_thread+0xef/0x172 [ 17.772655] [] ? worker_thread+0x0/0x172 [ 17.772658] [] ? worker_thread+0x0/0x172 [ 17.772663] [] ? kthread+0x7a/0x82 [ 17.772668] [] ? kernel_thread_helper+0x4/0x10 [ 17.772671] [] ? kthread+0x0/0x82 [ 17.772674] [] ? kernel_thread_helper+0x0/0x10 Reported-by: Frederik Himpe References: https://bugs.freedesktop.org/show_bug.cgi?id=36394 Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 26 ++++++++++++++++++++++---- include/drm/drm_fb_helper.h | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 11d7a72c22d..140b9525b48 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1516,17 +1516,33 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) } EXPORT_SYMBOL(drm_fb_helper_initial_config); -bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) +/** + * drm_fb_helper_hotplug_event - respond to a hotplug notification by + * probing all the outputs attached to the fb. + * @fb_helper: the drm_fb_helper + * + * LOCKING: + * Called at runtime, must take mode config lock. + * + * Scan the connectors attached to the fb_helper and try to put together a + * setup after *notification of a change in output configuration. + * + * RETURNS: + * 0 on success and a non-zero error code otherwise. + */ +int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) { + struct drm_device *dev = fb_helper->dev; int count = 0; u32 max_width, max_height, bpp_sel; bool bound = false, crtcs_bound = false; struct drm_crtc *crtc; if (!fb_helper->fb) - return false; + return 0; - list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) { + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (crtc->fb) crtcs_bound = true; if (crtc->fb == fb_helper->fb) @@ -1535,7 +1551,8 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) if (!bound && crtcs_bound) { fb_helper->delayed_hotplug = true; - return false; + mutex_unlock(&dev->mode_config.mutex); + return 0; } DRM_DEBUG_KMS("\n"); @@ -1546,6 +1563,7 @@ bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) count = drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height); drm_setup_crtcs(fb_helper); + mutex_unlock(&dev->mode_config.mutex); return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); } diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index ade09d7b427..c99c3d3e781 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -127,7 +127,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info); -bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); +int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper); bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel); int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper); int drm_fb_helper_debug_enter(struct fb_info *info); -- cgit v1.2.3 From 5ad3d8831f0c97257460c11ddcc1cc0466c762d4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 17 Apr 2011 20:35:51 -0700 Subject: drm: Create and use drm_err Reduce drm text size ~1% by using drm_err and printf extension %pV to emit error messages. Remove unused macro DRM_MEM_ERROR. $ size drivers/gpu/drm/built-in.o* text data bss dec hex filename 361159 9663 256 371078 5a986 drivers/gpu/drm/built-in.o.new 365416 9663 256 375335 5ba27 drivers/gpu/drm/built-in.o.old Signed-off-by: Joe Perches Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_stub.c | 21 +++++++++++++++++++++ include/drm/drmP.h | 21 +++++++-------------- 2 files changed, 28 insertions(+), 14 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 001273d57f2..6d7b083c5b7 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -62,6 +62,26 @@ struct idr drm_minors_idr; struct class *drm_class; struct proc_dir_entry *drm_proc_root; struct dentry *drm_debugfs_root; + +int drm_err(const char *func, const char *format, ...) +{ + struct va_format vaf; + va_list args; + int r; + + va_start(args, format); + + vaf.fmt = format; + vaf.va = &args; + + r = printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf); + + va_end(args); + + return r; +} +EXPORT_SYMBOL(drm_err); + void drm_ut_debug_printk(unsigned int request_level, const char *prefix, const char *function_name, @@ -78,6 +98,7 @@ void drm_ut_debug_printk(unsigned int request_level, } } EXPORT_SYMBOL(drm_ut_debug_printk); + static int drm_minor_get_id(struct drm_device *dev, int type) { int new_id; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 202424d17ed..22db51d1061 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -126,6 +126,9 @@ extern void drm_ut_debug_printk(unsigned int request_level, const char *prefix, const char *function_name, const char *format, ...); +extern __attribute__((format (printf, 2, 3))) +int drm_err(const char *func, const char *format, ...); + /***********************************************************************/ /** \name DRM template customization defaults */ /*@{*/ @@ -181,21 +184,11 @@ extern void drm_ut_debug_printk(unsigned int request_level, * \param fmt printf() like format string. * \param arg arguments */ -#define DRM_ERROR(fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* " fmt , __func__ , ##arg) - -/** - * Memory error output. - * - * \param area memory area where the error occurred. - * \param fmt printf() like format string. - * \param arg arguments - */ -#define DRM_MEM_ERROR(area, fmt, arg...) \ - printk(KERN_ERR "[" DRM_NAME ":%s:%s] *ERROR* " fmt , __func__, \ - drm_mem_stats[area].name , ##arg) +#define DRM_ERROR(fmt, ...) \ + drm_err(__func__, fmt, ##__VA_ARGS__) -#define DRM_INFO(fmt, arg...) printk(KERN_INFO "[" DRM_NAME "] " fmt , ##arg) +#define DRM_INFO(fmt, ...) \ + printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__) /** * Debug output. -- cgit v1.2.3 From bbb0aef5cfe95fe9b51a7eeba4a440b69037b01f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 17 Apr 2011 20:35:52 -0700 Subject: drm: Verify debug message arguments Add __attribute__((format (printf, 4, 5))) to drm_ut_debug_printk and fix fallout. Signed-off-by: Joe Perches Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 9 +++++---- drivers/gpu/drm/i915/intel_bios.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- drivers/gpu/drm/radeon/radeon_display.c | 5 +++-- include/drm/drmP.h | 3 ++- 5 files changed, 17 insertions(+), 14 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 741457bd1c4..62ced7554ba 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -684,10 +684,11 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, */ *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns); - DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %d.%d -> %d.%d [e %d us, %d rep]\n", - crtc, (int) vbl_status, hpos, vpos, raw_time.tv_sec, - raw_time.tv_usec, vblank_time->tv_sec, vblank_time->tv_usec, - (int) duration_ns/1000, i); + DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", + crtc, (int)vbl_status, hpos, vpos, + (long)raw_time.tv_sec, (long)raw_time.tv_usec, + (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, + (int)duration_ns/1000, i); vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; if (invbl) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index fb5b4d426ae..927442a1192 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -214,9 +214,9 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, i915_lvds_downclock) { dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; - DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", - "Normal Clock %dKHz, downclock %dKHz\n", - temp_downclock, panel_fixed_mode->clock); + DRM_DEBUG_KMS("LVDS downclock is found in VBT. " + "Normal Clock %dKHz, downclock %dKHz\n", + temp_downclock, panel_fixed_mode->clock); } return; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e522c702b04..21a7e70feac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3497,11 +3497,11 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, 1000; entries_required = DIV_ROUND_UP(entries_required, wm->cacheline_size); - DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required); + DRM_DEBUG_KMS("FIFO entries required for mode: %ld\n", entries_required); wm_size = fifo_size - (entries_required + wm->guard_size); - DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size); + DRM_DEBUG_KMS("FIFO watermark level: %ld\n", wm_size); /* Don't promote wm_size to unsigned... */ if (wm_size > (long)wm->max_wm) @@ -3823,13 +3823,13 @@ static bool g4x_check_srwm(struct drm_device *dev, display_wm, cursor_wm); if (display_wm > display->max_wm) { - DRM_DEBUG_KMS("display watermark is too large(%d), disabling\n", + DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n", display_wm, display->max_wm); return false; } if (cursor_wm > cursor->max_wm) { - DRM_DEBUG_KMS("cursor watermark is too large(%d), disabling\n", + DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n", cursor_wm, cursor->max_wm); return false; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index bdbab5c43bd..06719340edc 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1087,8 +1087,9 @@ void radeon_compute_pll_legacy(struct radeon_pll *pll, *frac_fb_div_p = best_frac_feedback_div; *ref_div_p = best_ref_div; *post_div_p = best_post_div; - DRM_DEBUG_KMS("%d %d, pll dividers - fb: %d.%d ref: %d, post %d\n", - freq, best_freq / 1000, best_feedback_div, best_frac_feedback_div, + DRM_DEBUG_KMS("%lld %d, pll dividers - fb: %d.%d ref: %d, post %d\n", + (long long)freq, + best_freq / 1000, best_feedback_div, best_frac_feedback_div, best_ref_div, best_post_div); } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 22db51d1061..4ab866e73f4 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -122,7 +122,8 @@ struct drm_device; * using the DRM_DEBUG_KMS and DRM_DEBUG. */ -extern void drm_ut_debug_printk(unsigned int request_level, +extern __attribute__((format (printf, 4, 5))) +void drm_ut_debug_printk(unsigned int request_level, const char *prefix, const char *function_name, const char *format, ...); -- cgit v1.2.3 From 1794d257fa7bab3ea5162f8abdca749996b65343 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 17 Apr 2011 07:43:32 +0100 Subject: drm: Export the command-line mode parser In the absence of configuration data for providing the fixed mode for a panel, I would like to be able to pass such modes along a separate module paramenter. To do so, I then need to parse a modeline from a string, which drm is already capable of. Export that capability to the drivers. Signed-off-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 207 +++++++--------------------------------- drivers/gpu/drm/drm_modes.c | 154 ++++++++++++++++++++++++++++++ include/drm/drmP.h | 25 +++++ include/drm/drm_fb_helper.h | 16 +--- 4 files changed, 216 insertions(+), 186 deletions(-) (limited to 'include/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 140b9525b48..802b61ac313 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -70,174 +70,50 @@ fail: } EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); -/** - * drm_fb_helper_connector_parse_command_line - parse command line for connector - * @connector - connector to parse line for - * @mode_option - per connector mode option - * - * This parses the connector specific then generic command lines for - * modes and options to configure the connector. - * - * This uses the same parameters as the fb modedb.c, except for extra - * x[M][R][-][@][i][m][eDd] - * - * enable/enable Digital/disable bit at the end - */ -static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_connector *fb_helper_conn, - const char *mode_option) -{ - const char *name; - unsigned int namelen; - int res_specified = 0, bpp_specified = 0, refresh_specified = 0; - unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0; - int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; - int i; - enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; - struct drm_fb_helper_cmdline_mode *cmdline_mode; - struct drm_connector *connector; - - if (!fb_helper_conn) - return false; - connector = fb_helper_conn->connector; - - cmdline_mode = &fb_helper_conn->cmdline_mode; - if (!mode_option) - mode_option = fb_mode_option; - - if (!mode_option) { - cmdline_mode->specified = false; - return false; - } - - name = mode_option; - namelen = strlen(name); - for (i = namelen-1; i >= 0; i--) { - switch (name[i]) { - case '@': - namelen = i; - if (!refresh_specified && !bpp_specified && - !yres_specified) { - refresh = simple_strtol(&name[i+1], NULL, 10); - refresh_specified = 1; - if (cvt || rb) - cvt = 0; - } else - goto done; - break; - case '-': - namelen = i; - if (!bpp_specified && !yres_specified) { - bpp = simple_strtol(&name[i+1], NULL, 10); - bpp_specified = 1; - if (cvt || rb) - cvt = 0; - } else - goto done; - break; - case 'x': - if (!yres_specified) { - yres = simple_strtol(&name[i+1], NULL, 10); - yres_specified = 1; - } else - goto done; - case '0' ... '9': - break; - case 'M': - if (!yres_specified) - cvt = 1; - break; - case 'R': - if (cvt) - rb = 1; - break; - case 'm': - if (!cvt) - margins = 1; - break; - case 'i': - if (!cvt) - interlace = 1; - break; - case 'e': - force = DRM_FORCE_ON; - break; - case 'D': - if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) && - (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) - force = DRM_FORCE_ON; - else - force = DRM_FORCE_ON_DIGITAL; - break; - case 'd': - force = DRM_FORCE_OFF; - break; - default: - goto done; - } - } - if (i < 0 && yres_specified) { - xres = simple_strtol(name, NULL, 10); - res_specified = 1; - } -done: - - DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", - drm_get_connector_name(connector), xres, yres, - (refresh) ? refresh : 60, (rb) ? " reduced blanking" : - "", (margins) ? " with margins" : "", (interlace) ? - " interlaced" : ""); - - if (force) { - const char *s; - switch (force) { - case DRM_FORCE_OFF: s = "OFF"; break; - case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break; - default: - case DRM_FORCE_ON: s = "ON"; break; - } - - DRM_INFO("forcing %s connector %s\n", - drm_get_connector_name(connector), s); - connector->force = force; - } - - if (res_specified) { - cmdline_mode->specified = true; - cmdline_mode->xres = xres; - cmdline_mode->yres = yres; - } - - if (refresh_specified) { - cmdline_mode->refresh_specified = true; - cmdline_mode->refresh = refresh; - } - - if (bpp_specified) { - cmdline_mode->bpp_specified = true; - cmdline_mode->bpp = bpp; - } - cmdline_mode->rb = rb ? true : false; - cmdline_mode->cvt = cvt ? true : false; - cmdline_mode->interlace = interlace ? true : false; - - return true; -} - static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) { struct drm_fb_helper_connector *fb_helper_conn; int i; for (i = 0; i < fb_helper->connector_count; i++) { + struct drm_cmdline_mode *mode; + struct drm_connector *connector; char *option = NULL; fb_helper_conn = fb_helper->connector_info[i]; + connector = fb_helper_conn->connector; + mode = &fb_helper_conn->cmdline_mode; /* do something on return - turn off connector maybe */ - if (fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option)) + if (fb_get_options(drm_get_connector_name(connector), &option)) continue; - drm_fb_helper_connector_parse_command_line(fb_helper_conn, option); + if (drm_mode_parse_command_line_for_connector(option, + connector, + mode)) { + if (mode->force) { + const char *s; + switch (mode->force) { + case DRM_FORCE_OFF: s = "OFF"; break; + case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break; + default: + case DRM_FORCE_ON: s = "ON"; break; + } + + DRM_INFO("forcing %s connector %s\n", + drm_get_connector_name(connector), s); + connector->force = mode->force; + } + + DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", + drm_get_connector_name(connector), + mode->xres, mode->yres, + mode->refresh_specified ? mode->refresh : 60, + mode->rb ? " reduced blanking" : "", + mode->margins ? " with margins" : "", + mode->interlace ? " interlaced" : ""); + } + } return 0; } @@ -901,7 +777,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, /* first up get a count of crtcs now in use and new min/maxes width/heights */ for (i = 0; i < fb_helper->connector_count; i++) { struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; - struct drm_fb_helper_cmdline_mode *cmdline_mode; + struct drm_cmdline_mode *cmdline_mode; cmdline_mode = &fb_helper_conn->cmdline_mode; @@ -1123,7 +999,7 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_conn static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) { - struct drm_fb_helper_cmdline_mode *cmdline_mode; + struct drm_cmdline_mode *cmdline_mode; cmdline_mode = &fb_connector->cmdline_mode; return cmdline_mode->specified; } @@ -1131,7 +1007,7 @@ static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, int width, int height) { - struct drm_fb_helper_cmdline_mode *cmdline_mode; + struct drm_cmdline_mode *cmdline_mode; struct drm_display_mode *mode = NULL; cmdline_mode = &fb_helper_conn->cmdline_mode; @@ -1163,19 +1039,8 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne } create_mode: - if (cmdline_mode->cvt) - mode = drm_cvt_mode(fb_helper_conn->connector->dev, - cmdline_mode->xres, cmdline_mode->yres, - cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, - cmdline_mode->rb, cmdline_mode->interlace, - cmdline_mode->margins); - else - mode = drm_gtf_mode(fb_helper_conn->connector->dev, - cmdline_mode->xres, cmdline_mode->yres, - cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60, - cmdline_mode->interlace, - cmdline_mode->margins); - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev, + cmdline_mode); list_add(&mode->head, &fb_helper_conn->connector->modes); return mode; } diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 25bf87390f5..207b7ebf815 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -974,3 +974,157 @@ void drm_mode_connector_list_update(struct drm_connector *connector) } } EXPORT_SYMBOL(drm_mode_connector_list_update); + +/** + * drm_mode_parse_command_line_for_connector - parse command line for connector + * @mode_option - per connector mode option + * @connector - connector to parse line for + * + * This parses the connector specific then generic command lines for + * modes and options to configure the connector. + * + * This uses the same parameters as the fb modedb.c, except for extra + * x[M][R][-][@][i][m][eDd] + * + * enable/enable Digital/disable bit at the end + */ +bool drm_mode_parse_command_line_for_connector(const char *mode_option, + struct drm_connector *connector, + struct drm_cmdline_mode *mode) +{ + const char *name; + unsigned int namelen; + int res_specified = 0, bpp_specified = 0, refresh_specified = 0; + unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0; + int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; + int i; + enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; + + if (!mode_option) + mode_option = fb_mode_option; + + if (!mode_option) { + mode->specified = false; + return false; + } + + name = mode_option; + namelen = strlen(name); + for (i = namelen-1; i >= 0; i--) { + switch (name[i]) { + case '@': + namelen = i; + if (!refresh_specified && !bpp_specified && + !yres_specified) { + refresh = simple_strtol(&name[i+1], NULL, 10); + refresh_specified = 1; + if (cvt || rb) + cvt = 0; + } else + goto done; + break; + case '-': + namelen = i; + if (!bpp_specified && !yres_specified) { + bpp = simple_strtol(&name[i+1], NULL, 10); + bpp_specified = 1; + if (cvt || rb) + cvt = 0; + } else + goto done; + break; + case 'x': + if (!yres_specified) { + yres = simple_strtol(&name[i+1], NULL, 10); + yres_specified = 1; + } else + goto done; + case '0' ... '9': + break; + case 'M': + if (!yres_specified) + cvt = 1; + break; + case 'R': + if (cvt) + rb = 1; + break; + case 'm': + if (!cvt) + margins = 1; + break; + case 'i': + if (!cvt) + interlace = 1; + break; + case 'e': + force = DRM_FORCE_ON; + break; + case 'D': + if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) && + (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) + force = DRM_FORCE_ON; + else + force = DRM_FORCE_ON_DIGITAL; + break; + case 'd': + force = DRM_FORCE_OFF; + break; + default: + goto done; + } + } + if (i < 0 && yres_specified) { + xres = simple_strtol(name, NULL, 10); + res_specified = 1; + } +done: + if (res_specified) { + mode->specified = true; + mode->xres = xres; + mode->yres = yres; + } + + if (refresh_specified) { + mode->refresh_specified = true; + mode->refresh = refresh; + } + + if (bpp_specified) { + mode->bpp_specified = true; + mode->bpp = bpp; + } + mode->rb = rb ? true : false; + mode->cvt = cvt ? true : false; + mode->interlace = interlace ? true : false; + mode->force = force; + + return true; +} +EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector); + +struct drm_display_mode * +drm_mode_create_from_cmdline_mode(struct drm_device *dev, + struct drm_cmdline_mode *cmd) +{ + struct drm_display_mode *mode; + + if (cmd->cvt) + mode = drm_cvt_mode(dev, + cmd->xres, cmd->yres, + cmd->refresh_specified ? cmd->refresh : 60, + cmd->rb, cmd->interlace, + cmd->margins); + else + mode = drm_gtf_mode(dev, + cmd->xres, cmd->yres, + cmd->refresh_specified ? cmd->refresh : 60, + cmd->interlace, + cmd->margins); + if (!mode) + return NULL; + + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + return mode; +} +EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 4ab866e73f4..738b3a5faa1 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -994,6 +994,22 @@ struct drm_minor { struct drm_mode_group mode_group; }; +/* mode specified on the command line */ +struct drm_cmdline_mode { + bool specified; + bool refresh_specified; + bool bpp_specified; + int xres, yres; + int bpp; + int refresh; + bool rb; + bool interlace; + bool cvt; + bool margins; + enum drm_connector_force force; +}; + + struct drm_pending_vblank_event { struct drm_pending_event base; int pipe; @@ -1389,6 +1405,15 @@ extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, struct drm_crtc *refcrtc); extern void drm_calc_timestamping_constants(struct drm_crtc *crtc); +extern bool +drm_mode_parse_command_line_for_connector(const char *mode_option, + struct drm_connector *connector, + struct drm_cmdline_mode *mode); + +extern struct drm_display_mode * +drm_mode_create_from_cmdline_mode(struct drm_device *dev, + struct drm_cmdline_mode *cmd); + /* Modesetting support */ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index c99c3d3e781..6e3076ad646 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -40,20 +40,6 @@ struct drm_fb_helper_crtc { struct drm_display_mode *desired_mode; }; -/* mode specified on the command line */ -struct drm_fb_helper_cmdline_mode { - bool specified; - bool refresh_specified; - bool bpp_specified; - int xres, yres; - int bpp; - int refresh; - bool rb; - bool interlace; - bool cvt; - bool margins; -}; - struct drm_fb_helper_surface_size { u32 fb_width; u32 fb_height; @@ -74,8 +60,8 @@ struct drm_fb_helper_funcs { }; struct drm_fb_helper_connector { - struct drm_fb_helper_cmdline_mode cmdline_mode; struct drm_connector *connector; + struct drm_cmdline_mode cmdline_mode; }; struct drm_fb_helper { -- cgit v1.2.3 From 428c4b51b7e133202db49021011f6af64b3276f8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 20 May 2011 04:34:25 -0400 Subject: drm/dp: add some new DP regs for DP 1.2 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- include/drm/drm_dp_helper.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include/drm') diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 83a389e4454..91567bbdb02 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -53,6 +53,7 @@ #define DP_MAX_LANE_COUNT 0x002 # define DP_MAX_LANE_COUNT_MASK 0x1f +# define DP_TPS3_SUPPORTED (1 << 6) # define DP_ENHANCED_FRAME_CAP (1 << 7) #define DP_MAX_DOWNSPREAD 0x003 @@ -71,10 +72,13 @@ #define DP_MAIN_LINK_CHANNEL_CODING 0x006 +#define DP_TRAINING_AUX_RD_INTERVAL 0x00e + /* link configuration */ #define DP_LINK_BW_SET 0x100 # define DP_LINK_BW_1_62 0x06 # define DP_LINK_BW_2_7 0x0a +# define DP_LINK_BW_5_4 0x14 #define DP_LANE_COUNT_SET 0x101 # define DP_LANE_COUNT_MASK 0x0f @@ -84,6 +88,7 @@ # define DP_TRAINING_PATTERN_DISABLE 0 # define DP_TRAINING_PATTERN_1 1 # define DP_TRAINING_PATTERN_2 2 +# define DP_TRAINING_PATTERN_3 3 # define DP_TRAINING_PATTERN_MASK 0x3 # define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) -- cgit v1.2.3