aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_modes.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r--drivers/gpu/drm/drm_modes.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 1c72208d8133..14b746f7ba97 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -35,6 +35,7 @@
#include <linux/list_sort.h>
#include <linux/export.h>
+#include <video/of_display_timing.h>
#include <video/of_videomode.h>
#include <video/videomode.h>
@@ -127,7 +128,7 @@ EXPORT_SYMBOL(drm_mode_probed_add);
* according to the hdisplay, vdisplay, vrefresh.
* It is based from the VESA(TM) Coordinated Video Timing Generator by
* Graham Loveridge April 9, 2003 available at
- * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
+ * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
*
* And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
* What I have done is to translate it by using integer calculation.
@@ -727,6 +728,54 @@ int of_get_drm_display_mode(struct device_node *np,
return 0;
}
EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
+
+/**
+ * of_get_drm_panel_display_mode - get a panel-timing drm_display_mode from devicetree
+ * @np: device_node with the panel-timing specification
+ * @dmode: will be set to the return value
+ * @bus_flags: information about pixelclk, sync and DE polarity
+ *
+ * The mandatory Device Tree properties width-mm and height-mm
+ * are read and set on the display mode.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int of_get_drm_panel_display_mode(struct device_node *np,
+ struct drm_display_mode *dmode, u32 *bus_flags)
+{
+ u32 width_mm = 0, height_mm = 0;
+ struct display_timing timing;
+ struct videomode vm;
+ int ret;
+
+ ret = of_get_display_timing(np, "panel-timing", &timing);
+ if (ret)
+ return ret;
+
+ videomode_from_timing(&timing, &vm);
+
+ memset(dmode, 0, sizeof(*dmode));
+ drm_display_mode_from_videomode(&vm, dmode);
+ if (bus_flags)
+ drm_bus_flags_from_videomode(&vm, bus_flags);
+
+ ret = of_property_read_u32(np, "width-mm", &width_mm);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "height-mm", &height_mm);
+ if (ret)
+ return ret;
+
+ dmode->width_mm = width_mm;
+ dmode->height_mm = height_mm;
+
+ drm_mode_debug_printmodeline(dmode);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_drm_panel_display_mode);
#endif /* CONFIG_OF */
#endif /* CONFIG_VIDEOMODE_HELPERS */
@@ -788,7 +837,9 @@ EXPORT_SYMBOL(drm_mode_vrefresh);
void drm_mode_get_hv_timing(const struct drm_display_mode *mode,
int *hdisplay, int *vdisplay)
{
- struct drm_display_mode adjusted = *mode;
+ struct drm_display_mode adjusted;
+
+ drm_mode_init(&adjusted, mode);
drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
*hdisplay = adjusted.crtc_hdisplay;
@@ -880,7 +931,7 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo);
* @dst: mode to overwrite
* @src: mode to copy
*
- * Copy an existing mode into another mode, preserving the object id and
+ * Copy an existing mode into another mode, preserving the
* list head of the destination mode.
*/
void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
@@ -893,6 +944,23 @@ void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *
EXPORT_SYMBOL(drm_mode_copy);
/**
+ * drm_mode_init - initialize the mode from another mode
+ * @dst: mode to overwrite
+ * @src: mode to copy
+ *
+ * Copy an existing mode into another mode, zeroing the
+ * list head of the destination mode. Typically used
+ * to guarantee the list head is not left with stack
+ * garbage in on-stack modes.
+ */
+void drm_mode_init(struct drm_display_mode *dst, const struct drm_display_mode *src)
+{
+ memset(dst, 0, sizeof(*dst));
+ drm_mode_copy(dst, src);
+}
+EXPORT_SYMBOL(drm_mode_init);
+
+/**
* drm_mode_duplicate - allocate and duplicate an existing mode
* @dev: drm_device to allocate the duplicated mode for
* @mode: mode to duplicate