Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'of_videomode_helper' of git://git.pengutronix.de/git/str/linux into drm-next

videomode helpers for of + devicetree stuff, required for new kms drivers

(not the fbdev maintainer).

* tag 'of_videomode_helper' of git://git.pengutronix.de/git/str/linux:
drm_modes: add of_videomode helpers
drm_modes: add videomode helpers
fbmon: add of_videomode helpers
fbmon: add videomode helpers
video: add of helper for display timings/videomode
video: add display_timing and videomode
viafb: rename display_timing to via_display_timing

+894 -13
+109
Documentation/devicetree/bindings/video/display-timing.txt
··· 1 + display-timing bindings 2 + ======================= 3 + 4 + display-timings node 5 + -------------------- 6 + 7 + required properties: 8 + - none 9 + 10 + optional properties: 11 + - native-mode: The native mode for the display, in case multiple modes are 12 + provided. When omitted, assume the first node is the native. 13 + 14 + timing subnode 15 + -------------- 16 + 17 + required properties: 18 + - hactive, vactive: display resolution 19 + - hfront-porch, hback-porch, hsync-len: horizontal display timing parameters 20 + in pixels 21 + vfront-porch, vback-porch, vsync-len: vertical display timing parameters in 22 + lines 23 + - clock-frequency: display clock in Hz 24 + 25 + optional properties: 26 + - hsync-active: hsync pulse is active low/high/ignored 27 + - vsync-active: vsync pulse is active low/high/ignored 28 + - de-active: data-enable pulse is active low/high/ignored 29 + - pixelclk-active: with 30 + - active high = drive pixel data on rising edge/ 31 + sample data on falling edge 32 + - active low = drive pixel data on falling edge/ 33 + sample data on rising edge 34 + - ignored = ignored 35 + - interlaced (bool): boolean to enable interlaced mode 36 + - doublescan (bool): boolean to enable doublescan mode 37 + 38 + All the optional properties that are not bool follow the following logic: 39 + <1>: high active 40 + <0>: low active 41 + omitted: not used on hardware 42 + 43 + There are different ways of describing the capabilities of a display. The 44 + devicetree representation corresponds to the one commonly found in datasheets 45 + for displays. If a display supports multiple signal timings, the native-mode 46 + can be specified. 47 + 48 + The parameters are defined as: 49 + 50 + +----------+-------------------------------------+----------+-------+ 51 + | | ↑ | | | 52 + | | |vback_porch | | | 53 + | | ↓ | | | 54 + +----------#######################################----------+-------+ 55 + | # ↑ # | | 56 + | # | # | | 57 + | hback # | # hfront | hsync | 58 + | porch # | hactive # porch | len | 59 + |<-------->#<-------+--------------------------->#<-------->|<----->| 60 + | # | # | | 61 + | # |vactive # | | 62 + | # | # | | 63 + | # ↓ # | | 64 + +----------#######################################----------+-------+ 65 + | | ↑ | | | 66 + | | |vfront_porch | | | 67 + | | ↓ | | | 68 + +----------+-------------------------------------+----------+-------+ 69 + | | ↑ | | | 70 + | | |vsync_len | | | 71 + | | ↓ | | | 72 + +----------+-------------------------------------+----------+-------+ 73 + 74 + Example: 75 + 76 + display-timings { 77 + native-mode = <&timing0>; 78 + timing0: 1080p24 { 79 + /* 1920x1080p24 */ 80 + clock-frequency = <52000000>; 81 + hactive = <1920>; 82 + vactive = <1080>; 83 + hfront-porch = <25>; 84 + hback-porch = <25>; 85 + hsync-len = <25>; 86 + vback-porch = <2>; 87 + vfront-porch = <2>; 88 + vsync-len = <2>; 89 + hsync-active = <1>; 90 + }; 91 + }; 92 + 93 + Every required property also supports the use of ranges, so the commonly used 94 + datasheet description with minimum, typical and maximum values can be used. 95 + 96 + Example: 97 + 98 + timing1: timing { 99 + /* 1920x1080p24 */ 100 + clock-frequency = <148500000>; 101 + hactive = <1920>; 102 + vactive = <1080>; 103 + hsync-len = <0 44 60>; 104 + hfront-porch = <80 88 95>; 105 + hback-porch = <100 148 160>; 106 + vfront-porch = <0 4 6>; 107 + vback-porch = <0 36 50>; 108 + vsync-len = <0 5 6>; 109 + };
+70
drivers/gpu/drm/drm_modes.c
··· 35 35 #include <linux/export.h> 36 36 #include <drm/drmP.h> 37 37 #include <drm/drm_crtc.h> 38 + #include <video/of_videomode.h> 39 + #include <video/videomode.h> 38 40 39 41 /** 40 42 * drm_mode_debug_printmodeline - debug print a mode ··· 505 503 margins, 600, 40 * 2, 128, 20 * 2); 506 504 } 507 505 EXPORT_SYMBOL(drm_gtf_mode); 506 + 507 + #if IS_ENABLED(CONFIG_VIDEOMODE) 508 + int drm_display_mode_from_videomode(const struct videomode *vm, 509 + struct drm_display_mode *dmode) 510 + { 511 + dmode->hdisplay = vm->hactive; 512 + dmode->hsync_start = dmode->hdisplay + vm->hfront_porch; 513 + dmode->hsync_end = dmode->hsync_start + vm->hsync_len; 514 + dmode->htotal = dmode->hsync_end + vm->hback_porch; 515 + 516 + dmode->vdisplay = vm->vactive; 517 + dmode->vsync_start = dmode->vdisplay + vm->vfront_porch; 518 + dmode->vsync_end = dmode->vsync_start + vm->vsync_len; 519 + dmode->vtotal = dmode->vsync_end + vm->vback_porch; 520 + 521 + dmode->clock = vm->pixelclock / 1000; 522 + 523 + dmode->flags = 0; 524 + if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) 525 + dmode->flags |= DRM_MODE_FLAG_PHSYNC; 526 + else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW) 527 + dmode->flags |= DRM_MODE_FLAG_NHSYNC; 528 + if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH) 529 + dmode->flags |= DRM_MODE_FLAG_PVSYNC; 530 + else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW) 531 + dmode->flags |= DRM_MODE_FLAG_NVSYNC; 532 + if (vm->data_flags & DISPLAY_FLAGS_INTERLACED) 533 + dmode->flags |= DRM_MODE_FLAG_INTERLACE; 534 + if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN) 535 + dmode->flags |= DRM_MODE_FLAG_DBLSCAN; 536 + drm_mode_set_name(dmode); 537 + 538 + return 0; 539 + } 540 + EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode); 541 + #endif 542 + 543 + #if IS_ENABLED(CONFIG_OF_VIDEOMODE) 544 + /** 545 + * of_get_drm_display_mode - get a drm_display_mode from devicetree 546 + * @np: device_node with the timing specification 547 + * @dmode: will be set to the return value 548 + * @index: index into the list of display timings in devicetree 549 + * 550 + * This function is expensive and should only be used, if only one mode is to be 551 + * read from DT. To get multiple modes start with of_get_display_timings and 552 + * work with that instead. 553 + */ 554 + int of_get_drm_display_mode(struct device_node *np, 555 + struct drm_display_mode *dmode, int index) 556 + { 557 + struct videomode vm; 558 + int ret; 559 + 560 + ret = of_get_videomode(np, &vm, index); 561 + if (ret) 562 + return ret; 563 + 564 + drm_display_mode_from_videomode(&vm, dmode); 565 + 566 + pr_debug("%s: got %dx%d display mode from %s\n", 567 + of_node_full_name(np), vm.hactive, vm.vactive, np->name); 568 + drm_mode_debug_printmodeline(dmode); 569 + 570 + return 0; 571 + } 572 + EXPORT_SYMBOL_GPL(of_get_drm_display_mode); 573 + #endif 508 574 509 575 /** 510 576 * drm_mode_set_name - set the name on a mode
+21
drivers/video/Kconfig
··· 33 33 This framework adds support for low-level control of the video 34 34 output switch. 35 35 36 + config DISPLAY_TIMING 37 + bool 38 + 39 + config VIDEOMODE 40 + bool 41 + 42 + config OF_DISPLAY_TIMING 43 + bool "Enable device tree display timing support" 44 + depends on OF 45 + select DISPLAY_TIMING 46 + help 47 + helper to parse display timings from the devicetree 48 + 49 + config OF_VIDEOMODE 50 + bool "Enable device tree videomode support" 51 + depends on OF 52 + select VIDEOMODE 53 + select OF_DISPLAY_TIMING 54 + help 55 + helper to get videomodes from the devicetree 56 + 36 57 menuconfig FB 37 58 tristate "Support for frame buffer devices" 38 59 ---help---
+4
drivers/video/Makefile
··· 168 168 169 169 #video output switch sysfs driver 170 170 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o 171 + obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o 172 + obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o 173 + obj-$(CONFIG_VIDEOMODE) += videomode.o 174 + obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
+24
drivers/video/display_timing.c
··· 1 + /* 2 + * generic display timing functions 3 + * 4 + * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + 9 + #include <linux/export.h> 10 + #include <linux/slab.h> 11 + #include <video/display_timing.h> 12 + 13 + void display_timings_release(struct display_timings *disp) 14 + { 15 + if (disp->timings) { 16 + unsigned int i; 17 + 18 + for (i = 0; i < disp->num_timings; i++) 19 + kfree(disp->timings[i]); 20 + kfree(disp->timings); 21 + } 22 + kfree(disp); 23 + } 24 + EXPORT_SYMBOL_GPL(display_timings_release);
+94
drivers/video/fbmon.c
··· 31 31 #include <linux/pci.h> 32 32 #include <linux/slab.h> 33 33 #include <video/edid.h> 34 + #include <video/of_videomode.h> 35 + #include <video/videomode.h> 34 36 #ifdef CONFIG_PPC_OF 35 37 #include <asm/prom.h> 36 38 #include <asm/pci-bridge.h> ··· 1375 1373 kfree(timings); 1376 1374 return err; 1377 1375 } 1376 + 1377 + #if IS_ENABLED(CONFIG_VIDEOMODE) 1378 + int fb_videomode_from_videomode(const struct videomode *vm, 1379 + struct fb_videomode *fbmode) 1380 + { 1381 + unsigned int htotal, vtotal; 1382 + 1383 + fbmode->xres = vm->hactive; 1384 + fbmode->left_margin = vm->hback_porch; 1385 + fbmode->right_margin = vm->hfront_porch; 1386 + fbmode->hsync_len = vm->hsync_len; 1387 + 1388 + fbmode->yres = vm->vactive; 1389 + fbmode->upper_margin = vm->vback_porch; 1390 + fbmode->lower_margin = vm->vfront_porch; 1391 + fbmode->vsync_len = vm->vsync_len; 1392 + 1393 + /* prevent division by zero in KHZ2PICOS macro */ 1394 + fbmode->pixclock = vm->pixelclock ? 1395 + KHZ2PICOS(vm->pixelclock / 1000) : 0; 1396 + 1397 + fbmode->sync = 0; 1398 + fbmode->vmode = 0; 1399 + if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) 1400 + fbmode->sync |= FB_SYNC_HOR_HIGH_ACT; 1401 + if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH) 1402 + fbmode->sync |= FB_SYNC_VERT_HIGH_ACT; 1403 + if (vm->data_flags & DISPLAY_FLAGS_INTERLACED) 1404 + fbmode->vmode |= FB_VMODE_INTERLACED; 1405 + if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN) 1406 + fbmode->vmode |= FB_VMODE_DOUBLE; 1407 + fbmode->flag = 0; 1408 + 1409 + htotal = vm->hactive + vm->hfront_porch + vm->hback_porch + 1410 + vm->hsync_len; 1411 + vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch + 1412 + vm->vsync_len; 1413 + /* prevent division by zero */ 1414 + if (htotal && vtotal) { 1415 + fbmode->refresh = vm->pixelclock / (htotal * vtotal); 1416 + /* a mode must have htotal and vtotal != 0 or it is invalid */ 1417 + } else { 1418 + fbmode->refresh = 0; 1419 + return -EINVAL; 1420 + } 1421 + 1422 + return 0; 1423 + } 1424 + EXPORT_SYMBOL_GPL(fb_videomode_from_videomode); 1425 + #endif 1426 + 1427 + #if IS_ENABLED(CONFIG_OF_VIDEOMODE) 1428 + static inline void dump_fb_videomode(const struct fb_videomode *m) 1429 + { 1430 + pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n", 1431 + m->xres, m->yres, m->refresh, m->pixclock, m->left_margin, 1432 + m->right_margin, m->upper_margin, m->lower_margin, 1433 + m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag); 1434 + } 1435 + 1436 + /** 1437 + * of_get_fb_videomode - get a fb_videomode from devicetree 1438 + * @np: device_node with the timing specification 1439 + * @fb: will be set to the return value 1440 + * @index: index into the list of display timings in devicetree 1441 + * 1442 + * DESCRIPTION: 1443 + * This function is expensive and should only be used, if only one mode is to be 1444 + * read from DT. To get multiple modes start with of_get_display_timings ond 1445 + * work with that instead. 1446 + */ 1447 + int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb, 1448 + int index) 1449 + { 1450 + struct videomode vm; 1451 + int ret; 1452 + 1453 + ret = of_get_videomode(np, &vm, index); 1454 + if (ret) 1455 + return ret; 1456 + 1457 + fb_videomode_from_videomode(&vm, fb); 1458 + 1459 + pr_debug("%s: got %dx%d display mode from %s\n", 1460 + of_node_full_name(np), vm.hactive, vm.vactive, np->name); 1461 + dump_fb_videomode(fb); 1462 + 1463 + return 0; 1464 + } 1465 + EXPORT_SYMBOL_GPL(of_get_fb_videomode); 1466 + #endif 1467 + 1378 1468 #else 1379 1469 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) 1380 1470 {
+239
drivers/video/of_display_timing.c
··· 1 + /* 2 + * OF helpers for parsing display timings 3 + * 4 + * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix 5 + * 6 + * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de> 7 + * 8 + * This file is released under the GPLv2 9 + */ 10 + #include <linux/export.h> 11 + #include <linux/of.h> 12 + #include <linux/slab.h> 13 + #include <video/display_timing.h> 14 + #include <video/of_display_timing.h> 15 + 16 + /** 17 + * parse_timing_property - parse timing_entry from device_node 18 + * @np: device_node with the property 19 + * @name: name of the property 20 + * @result: will be set to the return value 21 + * 22 + * DESCRIPTION: 23 + * Every display_timing can be specified with either just the typical value or 24 + * a range consisting of min/typ/max. This function helps handling this 25 + **/ 26 + static int parse_timing_property(struct device_node *np, const char *name, 27 + struct timing_entry *result) 28 + { 29 + struct property *prop; 30 + int length, cells, ret; 31 + 32 + prop = of_find_property(np, name, &length); 33 + if (!prop) { 34 + pr_err("%s: could not find property %s\n", 35 + of_node_full_name(np), name); 36 + return -EINVAL; 37 + } 38 + 39 + cells = length / sizeof(u32); 40 + if (cells == 1) { 41 + ret = of_property_read_u32(np, name, &result->typ); 42 + result->min = result->typ; 43 + result->max = result->typ; 44 + } else if (cells == 3) { 45 + ret = of_property_read_u32_array(np, name, &result->min, cells); 46 + } else { 47 + pr_err("%s: illegal timing specification in %s\n", 48 + of_node_full_name(np), name); 49 + return -EINVAL; 50 + } 51 + 52 + return ret; 53 + } 54 + 55 + /** 56 + * of_get_display_timing - parse display_timing entry from device_node 57 + * @np: device_node with the properties 58 + **/ 59 + static struct display_timing *of_get_display_timing(struct device_node *np) 60 + { 61 + struct display_timing *dt; 62 + u32 val = 0; 63 + int ret = 0; 64 + 65 + dt = kzalloc(sizeof(*dt), GFP_KERNEL); 66 + if (!dt) { 67 + pr_err("%s: could not allocate display_timing struct\n", 68 + of_node_full_name(np)); 69 + return NULL; 70 + } 71 + 72 + ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch); 73 + ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch); 74 + ret |= parse_timing_property(np, "hactive", &dt->hactive); 75 + ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len); 76 + ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch); 77 + ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch); 78 + ret |= parse_timing_property(np, "vactive", &dt->vactive); 79 + ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len); 80 + ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock); 81 + 82 + dt->dmt_flags = 0; 83 + dt->data_flags = 0; 84 + if (!of_property_read_u32(np, "vsync-active", &val)) 85 + dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH : 86 + VESA_DMT_VSYNC_LOW; 87 + if (!of_property_read_u32(np, "hsync-active", &val)) 88 + dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH : 89 + VESA_DMT_HSYNC_LOW; 90 + if (!of_property_read_u32(np, "de-active", &val)) 91 + dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH : 92 + DISPLAY_FLAGS_DE_LOW; 93 + if (!of_property_read_u32(np, "pixelclk-active", &val)) 94 + dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 95 + DISPLAY_FLAGS_PIXDATA_NEGEDGE; 96 + 97 + if (of_property_read_bool(np, "interlaced")) 98 + dt->data_flags |= DISPLAY_FLAGS_INTERLACED; 99 + if (of_property_read_bool(np, "doublescan")) 100 + dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN; 101 + 102 + if (ret) { 103 + pr_err("%s: error reading timing properties\n", 104 + of_node_full_name(np)); 105 + kfree(dt); 106 + return NULL; 107 + } 108 + 109 + return dt; 110 + } 111 + 112 + /** 113 + * of_get_display_timings - parse all display_timing entries from a device_node 114 + * @np: device_node with the subnodes 115 + **/ 116 + struct display_timings *of_get_display_timings(struct device_node *np) 117 + { 118 + struct device_node *timings_np; 119 + struct device_node *entry; 120 + struct device_node *native_mode; 121 + struct display_timings *disp; 122 + 123 + if (!np) { 124 + pr_err("%s: no devicenode given\n", of_node_full_name(np)); 125 + return NULL; 126 + } 127 + 128 + timings_np = of_find_node_by_name(np, "display-timings"); 129 + if (!timings_np) { 130 + pr_err("%s: could not find display-timings node\n", 131 + of_node_full_name(np)); 132 + return NULL; 133 + } 134 + 135 + disp = kzalloc(sizeof(*disp), GFP_KERNEL); 136 + if (!disp) { 137 + pr_err("%s: could not allocate struct disp'\n", 138 + of_node_full_name(np)); 139 + goto dispfail; 140 + } 141 + 142 + entry = of_parse_phandle(timings_np, "native-mode", 0); 143 + /* assume first child as native mode if none provided */ 144 + if (!entry) 145 + entry = of_get_next_child(np, NULL); 146 + /* if there is no child, it is useless to go on */ 147 + if (!entry) { 148 + pr_err("%s: no timing specifications given\n", 149 + of_node_full_name(np)); 150 + goto entryfail; 151 + } 152 + 153 + pr_debug("%s: using %s as default timing\n", 154 + of_node_full_name(np), entry->name); 155 + 156 + native_mode = entry; 157 + 158 + disp->num_timings = of_get_child_count(timings_np); 159 + if (disp->num_timings == 0) { 160 + /* should never happen, as entry was already found above */ 161 + pr_err("%s: no timings specified\n", of_node_full_name(np)); 162 + goto entryfail; 163 + } 164 + 165 + disp->timings = kzalloc(sizeof(struct display_timing *) * 166 + disp->num_timings, GFP_KERNEL); 167 + if (!disp->timings) { 168 + pr_err("%s: could not allocate timings array\n", 169 + of_node_full_name(np)); 170 + goto entryfail; 171 + } 172 + 173 + disp->num_timings = 0; 174 + disp->native_mode = 0; 175 + 176 + for_each_child_of_node(timings_np, entry) { 177 + struct display_timing *dt; 178 + 179 + dt = of_get_display_timing(entry); 180 + if (!dt) { 181 + /* 182 + * to not encourage wrong devicetrees, fail in case of 183 + * an error 184 + */ 185 + pr_err("%s: error in timing %d\n", 186 + of_node_full_name(np), disp->num_timings + 1); 187 + goto timingfail; 188 + } 189 + 190 + if (native_mode == entry) 191 + disp->native_mode = disp->num_timings; 192 + 193 + disp->timings[disp->num_timings] = dt; 194 + disp->num_timings++; 195 + } 196 + of_node_put(timings_np); 197 + /* 198 + * native_mode points to the device_node returned by of_parse_phandle 199 + * therefore call of_node_put on it 200 + */ 201 + of_node_put(native_mode); 202 + 203 + pr_debug("%s: got %d timings. Using timing #%d as default\n", 204 + of_node_full_name(np), disp->num_timings, 205 + disp->native_mode + 1); 206 + 207 + return disp; 208 + 209 + timingfail: 210 + if (native_mode) 211 + of_node_put(native_mode); 212 + display_timings_release(disp); 213 + entryfail: 214 + kfree(disp); 215 + dispfail: 216 + of_node_put(timings_np); 217 + return NULL; 218 + } 219 + EXPORT_SYMBOL_GPL(of_get_display_timings); 220 + 221 + /** 222 + * of_display_timings_exist - check if a display-timings node is provided 223 + * @np: device_node with the timing 224 + **/ 225 + int of_display_timings_exist(struct device_node *np) 226 + { 227 + struct device_node *timings_np; 228 + 229 + if (!np) 230 + return -EINVAL; 231 + 232 + timings_np = of_parse_phandle(np, "display-timings", 0); 233 + if (!timings_np) 234 + return -EINVAL; 235 + 236 + of_node_put(timings_np); 237 + return 1; 238 + } 239 + EXPORT_SYMBOL_GPL(of_display_timings_exist);
+54
drivers/video/of_videomode.c
··· 1 + /* 2 + * generic videomode helper 3 + * 4 + * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + #include <linux/errno.h> 9 + #include <linux/export.h> 10 + #include <linux/of.h> 11 + #include <video/display_timing.h> 12 + #include <video/of_display_timing.h> 13 + #include <video/of_videomode.h> 14 + #include <video/videomode.h> 15 + 16 + /** 17 + * of_get_videomode - get the videomode #<index> from devicetree 18 + * @np - devicenode with the display_timings 19 + * @vm - set to return value 20 + * @index - index into list of display_timings 21 + * (Set this to OF_USE_NATIVE_MODE to use whatever mode is 22 + * specified as native mode in the DT.) 23 + * 24 + * DESCRIPTION: 25 + * Get a list of all display timings and put the one 26 + * specified by index into *vm. This function should only be used, if 27 + * only one videomode is to be retrieved. A driver that needs to work 28 + * with multiple/all videomodes should work with 29 + * of_get_display_timings instead. 30 + **/ 31 + int of_get_videomode(struct device_node *np, struct videomode *vm, 32 + int index) 33 + { 34 + struct display_timings *disp; 35 + int ret; 36 + 37 + disp = of_get_display_timings(np); 38 + if (!disp) { 39 + pr_err("%s: no timings specified\n", of_node_full_name(np)); 40 + return -EINVAL; 41 + } 42 + 43 + if (index == OF_USE_NATIVE_MODE) 44 + index = disp->native_mode; 45 + 46 + ret = videomode_from_timing(disp, vm, index); 47 + if (ret) 48 + return ret; 49 + 50 + display_timings_release(disp); 51 + 52 + return 0; 53 + } 54 + EXPORT_SYMBOL_GPL(of_get_videomode);
+3 -3
drivers/video/via/hw.c
··· 1467 1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ 1468 1468 } 1469 1469 1470 - struct display_timing var_to_timing(const struct fb_var_screeninfo *var, 1470 + struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var, 1471 1471 u16 cxres, u16 cyres) 1472 1472 { 1473 - struct display_timing timing; 1473 + struct via_display_timing timing; 1474 1474 u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2; 1475 1475 1476 1476 timing.hor_addr = cxres; ··· 1491 1491 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, 1492 1492 u16 cxres, u16 cyres, int iga) 1493 1493 { 1494 - struct display_timing crt_reg = var_to_timing(var, 1494 + struct via_display_timing crt_reg = var_to_timing(var, 1495 1495 cxres ? cxres : var->xres, cyres ? cyres : var->yres); 1496 1496 1497 1497 if (iga == IGA1)
+1 -1
drivers/video/via/hw.h
··· 637 637 extern int viafb_DVI_ON; 638 638 extern int viafb_hotplug; 639 639 640 - struct display_timing var_to_timing(const struct fb_var_screeninfo *var, 640 + struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var, 641 641 u16 cxres, u16 cyres); 642 642 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, 643 643 u16 cxres, u16 cyres, int iga);
+1 -1
drivers/video/via/lcd.c
··· 549 549 int panel_hres = plvds_setting_info->lcd_panel_hres; 550 550 int panel_vres = plvds_setting_info->lcd_panel_vres; 551 551 u32 clock; 552 - struct display_timing timing; 552 + struct via_display_timing timing; 553 553 struct fb_var_screeninfo panel_var; 554 554 const struct fb_videomode *mode_crt_table, *panel_crt_table; 555 555
+1 -1
drivers/video/via/share.h
··· 319 319 int refresh_rate; 320 320 int h_sync_polarity; 321 321 int v_sync_polarity; 322 - struct display_timing crtc; 322 + struct via_display_timing crtc; 323 323 }; 324 324 325 325 struct io_reg {
+4 -4
drivers/video/via/via_modesetting.c
··· 30 30 #include "debug.h" 31 31 32 32 33 - void via_set_primary_timing(const struct display_timing *timing) 33 + void via_set_primary_timing(const struct via_display_timing *timing) 34 34 { 35 - struct display_timing raw; 35 + struct via_display_timing raw; 36 36 37 37 raw.hor_total = timing->hor_total / 8 - 5; 38 38 raw.hor_addr = timing->hor_addr / 8 - 1; ··· 88 88 via_write_reg_mask(VIACR, 0x17, 0x80, 0x80); 89 89 } 90 90 91 - void via_set_secondary_timing(const struct display_timing *timing) 91 + void via_set_secondary_timing(const struct via_display_timing *timing) 92 92 { 93 - struct display_timing raw; 93 + struct via_display_timing raw; 94 94 95 95 raw.hor_total = timing->hor_total - 1; 96 96 raw.hor_addr = timing->hor_addr - 1;
+3 -3
drivers/video/via/via_modesetting.h
··· 33 33 #define VIA_PITCH_MAX 0x3FF8 34 34 35 35 36 - struct display_timing { 36 + struct via_display_timing { 37 37 u16 hor_total; 38 38 u16 hor_addr; 39 39 u16 hor_blank_start; ··· 49 49 }; 50 50 51 51 52 - void via_set_primary_timing(const struct display_timing *timing); 53 - void via_set_secondary_timing(const struct display_timing *timing); 52 + void via_set_primary_timing(const struct via_display_timing *timing); 53 + void via_set_secondary_timing(const struct via_display_timing *timing); 54 54 void via_set_primary_address(u32 addr); 55 55 void via_set_secondary_address(u32 addr); 56 56 void via_set_primary_pitch(u32 pitch);
+39
drivers/video/videomode.c
··· 1 + /* 2 + * generic display timing functions 3 + * 4 + * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + 9 + #include <linux/errno.h> 10 + #include <linux/export.h> 11 + #include <video/display_timing.h> 12 + #include <video/videomode.h> 13 + 14 + int videomode_from_timing(const struct display_timings *disp, 15 + struct videomode *vm, unsigned int index) 16 + { 17 + struct display_timing *dt; 18 + 19 + dt = display_timings_get(disp, index); 20 + if (!dt) 21 + return -EINVAL; 22 + 23 + vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP); 24 + vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP); 25 + vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP); 26 + vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP); 27 + vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP); 28 + 29 + vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP); 30 + vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP); 31 + vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP); 32 + vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP); 33 + 34 + vm->dmt_flags = dt->dmt_flags; 35 + vm->data_flags = dt->data_flags; 36 + 37 + return 0; 38 + } 39 + EXPORT_SYMBOL_GPL(videomode_from_timing);
+9
include/drm/drmP.h
··· 85 85 struct drm_file; 86 86 struct drm_device; 87 87 88 + struct device_node; 89 + struct videomode; 90 + 88 91 #include <drm/drm_os_linux.h> 89 92 #include <drm/drm_hashtab.h> 90 93 #include <drm/drm_mm.h> ··· 1471 1468 extern struct drm_display_mode * 1472 1469 drm_mode_create_from_cmdline_mode(struct drm_device *dev, 1473 1470 struct drm_cmdline_mode *cmd); 1471 + 1472 + extern int drm_display_mode_from_videomode(const struct videomode *vm, 1473 + struct drm_display_mode *dmode); 1474 + extern int of_get_drm_display_mode(struct device_node *np, 1475 + struct drm_display_mode *dmode, 1476 + int index); 1474 1477 1475 1478 /* Modesetting support */ 1476 1479 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
+8
include/linux/fb.h
··· 19 19 struct fb_info; 20 20 struct device; 21 21 struct file; 22 + struct videomode; 23 + struct device_node; 22 24 23 25 /* Definitions below are used in the parsed monitor specs */ 24 26 #define FB_DPMS_ACTIVE_OFF 1 ··· 715 713 extern void fb_destroy_modedb(struct fb_videomode *modedb); 716 714 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb); 717 715 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter); 716 + 717 + extern int of_get_fb_videomode(struct device_node *np, 718 + struct fb_videomode *fb, 719 + int index); 720 + extern int fb_videomode_from_videomode(const struct videomode *vm, 721 + struct fb_videomode *fbmode); 718 722 719 723 /* drivers/video/modedb.c */ 720 724 #define VESA_MODEDB_SIZE 34
+124
include/video/display_timing.h
··· 1 + /* 2 + * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de> 3 + * 4 + * description of display timings 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + 9 + #ifndef __LINUX_DISPLAY_TIMING_H 10 + #define __LINUX_DISPLAY_TIMING_H 11 + 12 + #include <linux/bitops.h> 13 + #include <linux/types.h> 14 + 15 + /* VESA display monitor timing parameters */ 16 + #define VESA_DMT_HSYNC_LOW BIT(0) 17 + #define VESA_DMT_HSYNC_HIGH BIT(1) 18 + #define VESA_DMT_VSYNC_LOW BIT(2) 19 + #define VESA_DMT_VSYNC_HIGH BIT(3) 20 + 21 + /* display specific flags */ 22 + #define DISPLAY_FLAGS_DE_LOW BIT(0) /* data enable flag */ 23 + #define DISPLAY_FLAGS_DE_HIGH BIT(1) 24 + #define DISPLAY_FLAGS_PIXDATA_POSEDGE BIT(2) /* drive data on pos. edge */ 25 + #define DISPLAY_FLAGS_PIXDATA_NEGEDGE BIT(3) /* drive data on neg. edge */ 26 + #define DISPLAY_FLAGS_INTERLACED BIT(4) 27 + #define DISPLAY_FLAGS_DOUBLESCAN BIT(5) 28 + 29 + /* 30 + * A single signal can be specified via a range of minimal and maximal values 31 + * with a typical value, that lies somewhere inbetween. 32 + */ 33 + struct timing_entry { 34 + u32 min; 35 + u32 typ; 36 + u32 max; 37 + }; 38 + 39 + enum timing_entry_index { 40 + TE_MIN = 0, 41 + TE_TYP = 1, 42 + TE_MAX = 2, 43 + }; 44 + 45 + /* 46 + * Single "mode" entry. This describes one set of signal timings a display can 47 + * have in one setting. This struct can later be converted to struct videomode 48 + * (see include/video/videomode.h). As each timing_entry can be defined as a 49 + * range, one struct display_timing may become multiple struct videomodes. 50 + * 51 + * Example: hsync active high, vsync active low 52 + * 53 + * Active Video 54 + * Video ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________ 55 + * |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync.. 56 + * | | porch | | porch | 57 + * 58 + * HSync _|¯¯¯¯¯¯¯¯¯¯|___________________________________________|¯¯¯¯¯¯¯¯¯ 59 + * 60 + * VSync ¯|__________|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|_________ 61 + */ 62 + struct display_timing { 63 + struct timing_entry pixelclock; 64 + 65 + struct timing_entry hactive; /* hor. active video */ 66 + struct timing_entry hfront_porch; /* hor. front porch */ 67 + struct timing_entry hback_porch; /* hor. back porch */ 68 + struct timing_entry hsync_len; /* hor. sync len */ 69 + 70 + struct timing_entry vactive; /* ver. active video */ 71 + struct timing_entry vfront_porch; /* ver. front porch */ 72 + struct timing_entry vback_porch; /* ver. back porch */ 73 + struct timing_entry vsync_len; /* ver. sync len */ 74 + 75 + unsigned int dmt_flags; /* VESA DMT flags */ 76 + unsigned int data_flags; /* video data flags */ 77 + }; 78 + 79 + /* 80 + * This describes all timing settings a display provides. 81 + * The native_mode is the default setting for this display. 82 + * Drivers that can handle multiple videomodes should work with this struct and 83 + * convert each entry to the desired end result. 84 + */ 85 + struct display_timings { 86 + unsigned int num_timings; 87 + unsigned int native_mode; 88 + 89 + struct display_timing **timings; 90 + }; 91 + 92 + /* get value specified by index from struct timing_entry */ 93 + static inline u32 display_timing_get_value(const struct timing_entry *te, 94 + enum timing_entry_index index) 95 + { 96 + switch (index) { 97 + case TE_MIN: 98 + return te->min; 99 + break; 100 + case TE_TYP: 101 + return te->typ; 102 + break; 103 + case TE_MAX: 104 + return te->max; 105 + break; 106 + default: 107 + return te->typ; 108 + } 109 + } 110 + 111 + /* get one entry from struct display_timings */ 112 + static inline struct display_timing *display_timings_get(const struct 113 + display_timings *disp, 114 + unsigned int index) 115 + { 116 + if (disp->num_timings > index) 117 + return disp->timings[index]; 118 + else 119 + return NULL; 120 + } 121 + 122 + void display_timings_release(struct display_timings *disp); 123 + 124 + #endif
+20
include/video/of_display_timing.h
··· 1 + /* 2 + * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de> 3 + * 4 + * display timings of helpers 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + 9 + #ifndef __LINUX_OF_DISPLAY_TIMING_H 10 + #define __LINUX_OF_DISPLAY_TIMING_H 11 + 12 + struct device_node; 13 + struct display_timings; 14 + 15 + #define OF_USE_NATIVE_MODE -1 16 + 17 + struct display_timings *of_get_display_timings(struct device_node *np); 18 + int of_display_timings_exist(struct device_node *np); 19 + 20 + #endif
+18
include/video/of_videomode.h
··· 1 + /* 2 + * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de> 3 + * 4 + * videomode of-helpers 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + 9 + #ifndef __LINUX_OF_VIDEOMODE_H 10 + #define __LINUX_OF_VIDEOMODE_H 11 + 12 + struct device_node; 13 + struct videomode; 14 + 15 + int of_get_videomode(struct device_node *np, struct videomode *vm, 16 + int index); 17 + 18 + #endif /* __LINUX_OF_VIDEOMODE_H */
+48
include/video/videomode.h
··· 1 + /* 2 + * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de> 3 + * 4 + * generic videomode description 5 + * 6 + * This file is released under the GPLv2 7 + */ 8 + 9 + #ifndef __LINUX_VIDEOMODE_H 10 + #define __LINUX_VIDEOMODE_H 11 + 12 + #include <linux/types.h> 13 + #include <video/display_timing.h> 14 + 15 + /* 16 + * Subsystem independent description of a videomode. 17 + * Can be generated from struct display_timing. 18 + */ 19 + struct videomode { 20 + unsigned long pixelclock; /* pixelclock in Hz */ 21 + 22 + u32 hactive; 23 + u32 hfront_porch; 24 + u32 hback_porch; 25 + u32 hsync_len; 26 + 27 + u32 vactive; 28 + u32 vfront_porch; 29 + u32 vback_porch; 30 + u32 vsync_len; 31 + 32 + unsigned int dmt_flags; /* VESA DMT flags */ 33 + unsigned int data_flags; /* video data flags */ 34 + }; 35 + 36 + /** 37 + * videomode_from_timing - convert display timing to videomode 38 + * @disp: structure with all possible timing entries 39 + * @vm: return value 40 + * @index: index into the list of display timings in devicetree 41 + * 42 + * DESCRIPTION: 43 + * This function converts a struct display_timing to a struct videomode. 44 + */ 45 + int videomode_from_timing(const struct display_timings *disp, 46 + struct videomode *vm, unsigned int index); 47 + 48 + #endif