1 /* 2 * The list_sort function is (presumably) licensed under the GPL (see the 3 * top level "COPYING" file for details). 4 * 5 * The remainder of this file is: 6 * 7 * Copyright © 1997-2003 by The XFree86 Project, Inc. 8 * Copyright © 2007 Dave Airlie 9 * Copyright © 2007-2008 Intel Corporation 10 * Jesse Barnes <jesse.barnes@intel.com> 11 * Copyright 2005-2006 Luc Verhaegen 12 * Copyright (c) 2001, Andy Ritger aritger@nvidia.com 13 * 14 * Permission is hereby granted, free of charge, to any person obtaining a 15 * copy of this software and associated documentation files (the "Software"), 16 * to deal in the Software without restriction, including without limitation 17 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 * and/or sell copies of the Software, and to permit persons to whom the 19 * Software is furnished to do so, subject to the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be included in 22 * all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 * OTHER DEALINGS IN THE SOFTWARE. 31 * 32 * Except as contained in this notice, the name of the copyright holder(s) 33 * and author(s) shall not be used in advertising or otherwise to promote 34 * the sale, use or other dealings in this Software without prior written 35 * authorization from the copyright holder(s) and author(s). 36 */ 37 38 #include <linux/list.h> 39 #include "drmP.h" 40 #include "drm.h" 41 #include "drm_crtc.h" 42 43 /** 44 * drm_mode_debug_printmodeline - debug print a mode 45 * @dev: DRM device 46 * @mode: mode to print 47 * 48 * LOCKING: 49 * None. 50 * 51 * Describe @mode using DRM_DEBUG. 52 */ 53 void drm_mode_debug_printmodeline(struct drm_display_mode *mode) 54 { 55 DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d " 56 "0x%x 0x%x\n", 57 mode->base.id, mode->name, mode->vrefresh, mode->clock, 58 mode->hdisplay, mode->hsync_start, 59 mode->hsync_end, mode->htotal, 60 mode->vdisplay, mode->vsync_start, 61 mode->vsync_end, mode->vtotal, mode->type, mode->flags); 62 } 63 EXPORT_SYMBOL(drm_mode_debug_printmodeline); 64 65 /** 66 * drm_cvt_mode -create a modeline based on CVT algorithm 67 * @dev: DRM device 68 * @hdisplay: hdisplay size 69 * @vdisplay: vdisplay size 70 * @vrefresh : vrefresh rate 71 * @reduced : Whether the GTF calculation is simplified 72 * @interlaced:Whether the interlace is supported 73 * 74 * LOCKING: 75 * none. 76 * 77 * return the modeline based on CVT algorithm 78 * 79 * This function is called to generate the modeline based on CVT algorithm 80 * according to the hdisplay, vdisplay, vrefresh. 81 * It is based from the VESA(TM) Coordinated Video Timing Generator by 82 * Graham Loveridge April 9, 2003 available at 83 * http://www.vesa.org/public/CVT/CVTd6r1.xls 84 * 85 * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c. 86 * What I have done is to translate it by using integer calculation. 87 */ 88 #define HV_FACTOR 1000 89 struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, 90 int vdisplay, int vrefresh, 91 bool reduced, bool interlaced, bool margins) 92 { 93 /* 1) top/bottom margin size (% of height) - default: 1.8, */ 94 #define CVT_MARGIN_PERCENTAGE 18 95 /* 2) character cell horizontal granularity (pixels) - default 8 */ 96 #define CVT_H_GRANULARITY 8 97 /* 3) Minimum vertical porch (lines) - default 3 */ 98 #define CVT_MIN_V_PORCH 3 99 /* 4) Minimum number of vertical back porch lines - default 6 */ 100 #define CVT_MIN_V_BPORCH 6 101 /* Pixel Clock step (kHz) */ 102 #define CVT_CLOCK_STEP 250 103 struct drm_display_mode *drm_mode; 104 unsigned int vfieldrate, hperiod; 105 int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; 106 int interlace; 107 108 /* allocate the drm_display_mode structure. If failure, we will 109 * return directly 110 */ 111 drm_mode = drm_mode_create(dev); 112 if (!drm_mode) 113 return NULL; 114 115 /* the CVT default refresh rate is 60Hz */ 116 if (!vrefresh) 117 vrefresh = 60; 118 119 /* the required field fresh rate */ 120 if (interlaced) 121 vfieldrate = vrefresh * 2; 122 else 123 vfieldrate = vrefresh; 124 125 /* horizontal pixels */ 126 hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY); 127 128 /* determine the left&right borders */ 129 hmargin = 0; 130 if (margins) { 131 hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; 132 hmargin -= hmargin % CVT_H_GRANULARITY; 133 } 134 /* find the total active pixels */ 135 drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin; 136 137 /* find the number of lines per field */ 138 if (interlaced) 139 vdisplay_rnd = vdisplay / 2; 140 else 141 vdisplay_rnd = vdisplay; 142 143 /* find the top & bottom borders */ 144 vmargin = 0; 145 if (margins) 146 vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; 147 148 drm_mode->vdisplay = vdisplay + 2 * vmargin; 149 150 /* Interlaced */ 151 if (interlaced) 152 interlace = 1; 153 else 154 interlace = 0; 155 156 /* Determine VSync Width from aspect ratio */ 157 if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay)) 158 vsync = 4; 159 else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay)) 160 vsync = 5; 161 else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay)) 162 vsync = 6; 163 else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay)) 164 vsync = 7; 165 else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay)) 166 vsync = 7; 167 else /* custom */ 168 vsync = 10; 169 170 if (!reduced) { 171 /* simplify the GTF calculation */ 172 /* 4) Minimum time of vertical sync + back porch interval (µs) 173 * default 550.0 174 */ 175 int tmp1, tmp2; 176 #define CVT_MIN_VSYNC_BP 550 177 /* 3) Nominal HSync width (% of line period) - default 8 */ 178 #define CVT_HSYNC_PERCENTAGE 8 179 unsigned int hblank_percentage; 180 int vsyncandback_porch, vback_porch, hblank; 181 182 /* estimated the horizontal period */ 183 tmp1 = HV_FACTOR * 1000000 - 184 CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate; 185 tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 + 186 interlace; 187 hperiod = tmp1 * 2 / (tmp2 * vfieldrate); 188 189 tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1; 190 /* 9. Find number of lines in sync + backporch */ 191 if (tmp1 < (vsync + CVT_MIN_V_PORCH)) 192 vsyncandback_porch = vsync + CVT_MIN_V_PORCH; 193 else 194 vsyncandback_porch = tmp1; 195 /* 10. Find number of lines in back porch */ 196 vback_porch = vsyncandback_porch - vsync; 197 drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + 198 vsyncandback_porch + CVT_MIN_V_PORCH; 199 /* 5) Definition of Horizontal blanking time limitation */ 200 /* Gradient (%/kHz) - default 600 */ 201 #define CVT_M_FACTOR 600 202 /* Offset (%) - default 40 */ 203 #define CVT_C_FACTOR 40 204 /* Blanking time scaling factor - default 128 */ 205 #define CVT_K_FACTOR 128 206 /* Scaling factor weighting - default 20 */ 207 #define CVT_J_FACTOR 20 208 #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256) 209 #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ 210 CVT_J_FACTOR) 211 /* 12. Find ideal blanking duty cycle from formula */ 212 hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME * 213 hperiod / 1000; 214 /* 13. Blanking time */ 215 if (hblank_percentage < 20 * HV_FACTOR) 216 hblank_percentage = 20 * HV_FACTOR; 217 hblank = drm_mode->hdisplay * hblank_percentage / 218 (100 * HV_FACTOR - hblank_percentage); 219 hblank -= hblank % (2 * CVT_H_GRANULARITY); 220 /* 14. find the total pixes per line */ 221 drm_mode->htotal = drm_mode->hdisplay + hblank; 222 drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2; 223 drm_mode->hsync_start = drm_mode->hsync_end - 224 (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100; 225 drm_mode->hsync_start += CVT_H_GRANULARITY - 226 drm_mode->hsync_start % CVT_H_GRANULARITY; 227 /* fill the Vsync values */ 228 drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH; 229 drm_mode->vsync_end = drm_mode->vsync_start + vsync; 230 } else { 231 /* Reduced blanking */ 232 /* Minimum vertical blanking interval time (µs)- default 460 */ 233 #define CVT_RB_MIN_VBLANK 460 234 /* Fixed number of clocks for horizontal sync */ 235 #define CVT_RB_H_SYNC 32 236 /* Fixed number of clocks for horizontal blanking */ 237 #define CVT_RB_H_BLANK 160 238 /* Fixed number of lines for vertical front porch - default 3*/ 239 #define CVT_RB_VFPORCH 3 240 int vbilines; 241 int tmp1, tmp2; 242 /* 8. Estimate Horizontal period. */ 243 tmp1 = HV_FACTOR * 1000000 - 244 CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate; 245 tmp2 = vdisplay_rnd + 2 * vmargin; 246 hperiod = tmp1 / (tmp2 * vfieldrate); 247 /* 9. Find number of lines in vertical blanking */ 248 vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1; 249 /* 10. Check if vertical blanking is sufficient */ 250 if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH)) 251 vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH; 252 /* 11. Find total number of lines in vertical field */ 253 drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines; 254 /* 12. Find total number of pixels in a line */ 255 drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK; 256 /* Fill in HSync values */ 257 drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2; 258 drm_mode->hsync_start = drm_mode->hsync_end = CVT_RB_H_SYNC; 259 } 260 /* 15/13. Find pixel clock frequency (kHz for xf86) */ 261 drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; 262 drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; 263 /* 18/16. Find actual vertical frame frequency */ 264 /* ignore - just set the mode flag for interlaced */ 265 if (interlaced) 266 drm_mode->vtotal *= 2; 267 /* Fill the mode line name */ 268 drm_mode_set_name(drm_mode); 269 if (reduced) 270 drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC | 271 DRM_MODE_FLAG_NVSYNC); 272 else 273 drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC | 274 DRM_MODE_FLAG_NHSYNC); 275 if (interlaced) 276 drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; 277 278 return drm_mode; 279 } 280 EXPORT_SYMBOL(drm_cvt_mode); 281 282 /** 283 * drm_gtf_mode - create the modeline based on GTF algorithm 284 * 285 * @dev :drm device 286 * @hdisplay :hdisplay size 287 * @vdisplay :vdisplay size 288 * @vrefresh :vrefresh rate. 289 * @interlaced :whether the interlace is supported 290 * @margins :whether the margin is supported 291 * 292 * LOCKING. 293 * none. 294 * 295 * return the modeline based on GTF algorithm 296 * 297 * This function is to create the modeline based on the GTF algorithm. 298 * Generalized Timing Formula is derived from: 299 * GTF Spreadsheet by Andy Morrish (1/5/97) 300 * available at http://www.vesa.org 301 * 302 * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c. 303 * What I have done is to translate it by using integer calculation. 304 * I also refer to the function of fb_get_mode in the file of 305 * drivers/video/fbmon.c 306 */ 307 struct drm_display_mode *drm_gtf_mode(struct drm_device *dev, int hdisplay, 308 int vdisplay, int vrefresh, 309 bool interlaced, int margins) 310 { 311 /* 1) top/bottom margin size (% of height) - default: 1.8, */ 312 #define GTF_MARGIN_PERCENTAGE 18 313 /* 2) character cell horizontal granularity (pixels) - default 8 */ 314 #define GTF_CELL_GRAN 8 315 /* 3) Minimum vertical porch (lines) - default 3 */ 316 #define GTF_MIN_V_PORCH 1 317 /* width of vsync in lines */ 318 #define V_SYNC_RQD 3 319 /* width of hsync as % of total line */ 320 #define H_SYNC_PERCENT 8 321 /* min time of vsync + back porch (microsec) */ 322 #define MIN_VSYNC_PLUS_BP 550 323 /* blanking formula gradient */ 324 #define GTF_M 600 325 /* blanking formula offset */ 326 #define GTF_C 40 327 /* blanking formula scaling factor */ 328 #define GTF_K 128 329 /* blanking formula scaling factor */ 330 #define GTF_J 20 331 /* C' and M' are part of the Blanking Duty Cycle computation */ 332 #define GTF_C_PRIME (((GTF_C - GTF_J) * GTF_K / 256) + GTF_J) 333 #define GTF_M_PRIME (GTF_K * GTF_M / 256) 334 struct drm_display_mode *drm_mode; 335 unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd; 336 int top_margin, bottom_margin; 337 int interlace; 338 unsigned int hfreq_est; 339 int vsync_plus_bp, vback_porch; 340 unsigned int vtotal_lines, vfieldrate_est, hperiod; 341 unsigned int vfield_rate, vframe_rate; 342 int left_margin, right_margin; 343 unsigned int total_active_pixels, ideal_duty_cycle; 344 unsigned int hblank, total_pixels, pixel_freq; 345 int hsync, hfront_porch, vodd_front_porch_lines; 346 unsigned int tmp1, tmp2; 347 348 drm_mode = drm_mode_create(dev); 349 if (!drm_mode) 350 return NULL; 351 352 /* 1. In order to give correct results, the number of horizontal 353 * pixels requested is first processed to ensure that it is divisible 354 * by the character size, by rounding it to the nearest character 355 * cell boundary: 356 */ 357 hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; 358 hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN; 359 360 /* 2. If interlace is requested, the number of vertical lines assumed 361 * by the calculation must be halved, as the computation calculates 362 * the number of vertical lines per field. 363 */ 364 if (interlaced) 365 vdisplay_rnd = vdisplay / 2; 366 else 367 vdisplay_rnd = vdisplay; 368 369 /* 3. Find the frame rate required: */ 370 if (interlaced) 371 vfieldrate_rqd = vrefresh * 2; 372 else 373 vfieldrate_rqd = vrefresh; 374 375 /* 4. Find number of lines in Top margin: */ 376 top_margin = 0; 377 if (margins) 378 top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / 379 1000; 380 /* 5. Find number of lines in bottom margin: */ 381 bottom_margin = top_margin; 382 383 /* 6. If interlace is required, then set variable interlace: */ 384 if (interlaced) 385 interlace = 1; 386 else 387 interlace = 0; 388 389 /* 7. Estimate the Horizontal frequency */ 390 { 391 tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500; 392 tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) * 393 2 + interlace; 394 hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1; 395 } 396 397 /* 8. Find the number of lines in V sync + back porch */ 398 /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */ 399 vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000; 400 vsync_plus_bp = (vsync_plus_bp + 500) / 1000; 401 /* 9. Find the number of lines in V back porch alone: */ 402 vback_porch = vsync_plus_bp - V_SYNC_RQD; 403 /* 10. Find the total number of lines in Vertical field period: */ 404 vtotal_lines = vdisplay_rnd + top_margin + bottom_margin + 405 vsync_plus_bp + GTF_MIN_V_PORCH; 406 /* 11. Estimate the Vertical field frequency: */ 407 vfieldrate_est = hfreq_est / vtotal_lines; 408 /* 12. Find the actual horizontal period: */ 409 hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines); 410 411 /* 13. Find the actual Vertical field frequency: */ 412 vfield_rate = hfreq_est / vtotal_lines; 413 /* 14. Find the Vertical frame frequency: */ 414 if (interlaced) 415 vframe_rate = vfield_rate / 2; 416 else 417 vframe_rate = vfield_rate; 418 /* 15. Find number of pixels in left margin: */ 419 if (margins) 420 left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / 421 1000; 422 else 423 left_margin = 0; 424 425 /* 16.Find number of pixels in right margin: */ 426 right_margin = left_margin; 427 /* 17.Find total number of active pixels in image and left and right */ 428 total_active_pixels = hdisplay_rnd + left_margin + right_margin; 429 /* 18.Find the ideal blanking duty cycle from blanking duty cycle */ 430 ideal_duty_cycle = GTF_C_PRIME * 1000 - 431 (GTF_M_PRIME * 1000000 / hfreq_est); 432 /* 19.Find the number of pixels in the blanking time to the nearest 433 * double character cell: */ 434 hblank = total_active_pixels * ideal_duty_cycle / 435 (100000 - ideal_duty_cycle); 436 hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN); 437 hblank = hblank * 2 * GTF_CELL_GRAN; 438 /* 20.Find total number of pixels: */ 439 total_pixels = total_active_pixels + hblank; 440 /* 21.Find pixel clock frequency: */ 441 pixel_freq = total_pixels * hfreq_est / 1000; 442 /* Stage 1 computations are now complete; I should really pass 443 * the results to another function and do the Stage 2 computations, 444 * but I only need a few more values so I'll just append the 445 * computations here for now */ 446 /* 17. Find the number of pixels in the horizontal sync period: */ 447 hsync = H_SYNC_PERCENT * total_pixels / 100; 448 hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; 449 hsync = hsync * GTF_CELL_GRAN; 450 /* 18. Find the number of pixels in horizontal front porch period */ 451 hfront_porch = hblank / 2 - hsync; 452 /* 36. Find the number of lines in the odd front porch period: */ 453 vodd_front_porch_lines = GTF_MIN_V_PORCH ; 454 455 /* finally, pack the results in the mode struct */ 456 drm_mode->hdisplay = hdisplay_rnd; 457 drm_mode->hsync_start = hdisplay_rnd + hfront_porch; 458 drm_mode->hsync_end = drm_mode->hsync_start + hsync; 459 drm_mode->htotal = total_pixels; 460 drm_mode->vdisplay = vdisplay_rnd; 461 drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines; 462 drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD; 463 drm_mode->vtotal = vtotal_lines; 464 465 drm_mode->clock = pixel_freq; 466 467 drm_mode_set_name(drm_mode); 468 drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC; 469 470 if (interlaced) { 471 drm_mode->vtotal *= 2; 472 drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; 473 } 474 475 return drm_mode; 476 } 477 EXPORT_SYMBOL(drm_gtf_mode); 478 /** 479 * drm_mode_set_name - set the name on a mode 480 * @mode: name will be set in this mode 481 * 482 * LOCKING: 483 * None. 484 * 485 * Set the name of @mode to a standard format. 486 */ 487 void drm_mode_set_name(struct drm_display_mode *mode) 488 { 489 snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode->hdisplay, 490 mode->vdisplay); 491 } 492 EXPORT_SYMBOL(drm_mode_set_name); 493 494 /** 495 * drm_mode_list_concat - move modes from one list to another 496 * @head: source list 497 * @new: dst list 498 * 499 * LOCKING: 500 * Caller must ensure both lists are locked. 501 * 502 * Move all the modes from @head to @new. 503 */ 504 void drm_mode_list_concat(struct list_head *head, struct list_head *new) 505 { 506 507 struct list_head *entry, *tmp; 508 509 list_for_each_safe(entry, tmp, head) { 510 list_move_tail(entry, new); 511 } 512 } 513 EXPORT_SYMBOL(drm_mode_list_concat); 514 515 /** 516 * drm_mode_width - get the width of a mode 517 * @mode: mode 518 * 519 * LOCKING: 520 * None. 521 * 522 * Return @mode's width (hdisplay) value. 523 * 524 * FIXME: is this needed? 525 * 526 * RETURNS: 527 * @mode->hdisplay 528 */ 529 int drm_mode_width(struct drm_display_mode *mode) 530 { 531 return mode->hdisplay; 532 533 } 534 EXPORT_SYMBOL(drm_mode_width); 535 536 /** 537 * drm_mode_height - get the height of a mode 538 * @mode: mode 539 * 540 * LOCKING: 541 * None. 542 * 543 * Return @mode's height (vdisplay) value. 544 * 545 * FIXME: is this needed? 546 * 547 * RETURNS: 548 * @mode->vdisplay 549 */ 550 int drm_mode_height(struct drm_display_mode *mode) 551 { 552 return mode->vdisplay; 553 } 554 EXPORT_SYMBOL(drm_mode_height); 555 556 /** drm_mode_hsync - get the hsync of a mode 557 * @mode: mode 558 * 559 * LOCKING: 560 * None. 561 * 562 * Return @modes's hsync rate in kHz, rounded to the nearest int. 563 */ 564 int drm_mode_hsync(struct drm_display_mode *mode) 565 { 566 unsigned int calc_val; 567 568 if (mode->hsync) 569 return mode->hsync; 570 571 if (mode->htotal < 0) 572 return 0; 573 574 calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */ 575 calc_val += 500; /* round to 1000Hz */ 576 calc_val /= 1000; /* truncate to kHz */ 577 578 return calc_val; 579 } 580 EXPORT_SYMBOL(drm_mode_hsync); 581 582 /** 583 * drm_mode_vrefresh - get the vrefresh of a mode 584 * @mode: mode 585 * 586 * LOCKING: 587 * None. 588 * 589 * Return @mode's vrefresh rate in Hz or calculate it if necessary. 590 * 591 * FIXME: why is this needed? shouldn't vrefresh be set already? 592 * 593 * RETURNS: 594 * Vertical refresh rate. It will be the result of actual value plus 0.5. 595 * If it is 70.288, it will return 70Hz. 596 * If it is 59.6, it will return 60Hz. 597 */ 598 int drm_mode_vrefresh(struct drm_display_mode *mode) 599 { 600 int refresh = 0; 601 unsigned int calc_val; 602 603 if (mode->vrefresh > 0) 604 refresh = mode->vrefresh; 605 else if (mode->htotal > 0 && mode->vtotal > 0) { 606 int vtotal; 607 vtotal = mode->vtotal; 608 /* work out vrefresh the value will be x1000 */ 609 calc_val = (mode->clock * 1000); 610 calc_val /= mode->htotal; 611 refresh = (calc_val + vtotal / 2) / vtotal; 612 613 if (mode->flags & DRM_MODE_FLAG_INTERLACE) 614 refresh *= 2; 615 if (mode->flags & DRM_MODE_FLAG_DBLSCAN) 616 refresh /= 2; 617 if (mode->vscan > 1) 618 refresh /= mode->vscan; 619 } 620 return refresh; 621 } 622 EXPORT_SYMBOL(drm_mode_vrefresh); 623 624 /** 625 * drm_mode_set_crtcinfo - set CRTC modesetting parameters 626 * @p: mode 627 * @adjust_flags: unused? (FIXME) 628 * 629 * LOCKING: 630 * None. 631 * 632 * Setup the CRTC modesetting parameters for @p, adjusting if necessary. 633 */ 634 void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags) 635 { 636 if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN)) 637 return; 638 639 p->crtc_hdisplay = p->hdisplay; 640 p->crtc_hsync_start = p->hsync_start; 641 p->crtc_hsync_end = p->hsync_end; 642 p->crtc_htotal = p->htotal; 643 p->crtc_hskew = p->hskew; 644 p->crtc_vdisplay = p->vdisplay; 645 p->crtc_vsync_start = p->vsync_start; 646 p->crtc_vsync_end = p->vsync_end; 647 p->crtc_vtotal = p->vtotal; 648 649 if (p->flags & DRM_MODE_FLAG_INTERLACE) { 650 if (adjust_flags & CRTC_INTERLACE_HALVE_V) { 651 p->crtc_vdisplay /= 2; 652 p->crtc_vsync_start /= 2; 653 p->crtc_vsync_end /= 2; 654 p->crtc_vtotal /= 2; 655 } 656 657 p->crtc_vtotal |= 1; 658 } 659 660 if (p->flags & DRM_MODE_FLAG_DBLSCAN) { 661 p->crtc_vdisplay *= 2; 662 p->crtc_vsync_start *= 2; 663 p->crtc_vsync_end *= 2; 664 p->crtc_vtotal *= 2; 665 } 666 667 if (p->vscan > 1) { 668 p->crtc_vdisplay *= p->vscan; 669 p->crtc_vsync_start *= p->vscan; 670 p->crtc_vsync_end *= p->vscan; 671 p->crtc_vtotal *= p->vscan; 672 } 673 674 p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay); 675 p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal); 676 p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay); 677 p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); 678 679 p->crtc_hadjusted = false; 680 p->crtc_vadjusted = false; 681 } 682 EXPORT_SYMBOL(drm_mode_set_crtcinfo); 683 684 685 /** 686 * drm_mode_duplicate - allocate and duplicate an existing mode 687 * @m: mode to duplicate 688 * 689 * LOCKING: 690 * None. 691 * 692 * Just allocate a new mode, copy the existing mode into it, and return 693 * a pointer to it. Used to create new instances of established modes. 694 */ 695 struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, 696 struct drm_display_mode *mode) 697 { 698 struct drm_display_mode *nmode; 699 int new_id; 700 701 nmode = drm_mode_create(dev); 702 if (!nmode) 703 return NULL; 704 705 new_id = nmode->base.id; 706 *nmode = *mode; 707 nmode->base.id = new_id; 708 INIT_LIST_HEAD(&nmode->head); 709 return nmode; 710 } 711 EXPORT_SYMBOL(drm_mode_duplicate); 712 713 /** 714 * drm_mode_equal - test modes for equality 715 * @mode1: first mode 716 * @mode2: second mode 717 * 718 * LOCKING: 719 * None. 720 * 721 * Check to see if @mode1 and @mode2 are equivalent. 722 * 723 * RETURNS: 724 * True if the modes are equal, false otherwise. 725 */ 726 bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2) 727 { 728 /* do clock check convert to PICOS so fb modes get matched 729 * the same */ 730 if (mode1->clock && mode2->clock) { 731 if (KHZ2PICOS(mode1->clock) != KHZ2PICOS(mode2->clock)) 732 return false; 733 } else if (mode1->clock != mode2->clock) 734 return false; 735 736 if (mode1->hdisplay == mode2->hdisplay && 737 mode1->hsync_start == mode2->hsync_start && 738 mode1->hsync_end == mode2->hsync_end && 739 mode1->htotal == mode2->htotal && 740 mode1->hskew == mode2->hskew && 741 mode1->vdisplay == mode2->vdisplay && 742 mode1->vsync_start == mode2->vsync_start && 743 mode1->vsync_end == mode2->vsync_end && 744 mode1->vtotal == mode2->vtotal && 745 mode1->vscan == mode2->vscan && 746 mode1->flags == mode2->flags) 747 return true; 748 749 return false; 750 } 751 EXPORT_SYMBOL(drm_mode_equal); 752 753 /** 754 * drm_mode_validate_size - make sure modes adhere to size constraints 755 * @dev: DRM device 756 * @mode_list: list of modes to check 757 * @maxX: maximum width 758 * @maxY: maximum height 759 * @maxPitch: max pitch 760 * 761 * LOCKING: 762 * Caller must hold a lock protecting @mode_list. 763 * 764 * The DRM device (@dev) has size and pitch limits. Here we validate the 765 * modes we probed for @dev against those limits and set their status as 766 * necessary. 767 */ 768 void drm_mode_validate_size(struct drm_device *dev, 769 struct list_head *mode_list, 770 int maxX, int maxY, int maxPitch) 771 { 772 struct drm_display_mode *mode; 773 774 list_for_each_entry(mode, mode_list, head) { 775 if (maxPitch > 0 && mode->hdisplay > maxPitch) 776 mode->status = MODE_BAD_WIDTH; 777 778 if (maxX > 0 && mode->hdisplay > maxX) 779 mode->status = MODE_VIRTUAL_X; 780 781 if (maxY > 0 && mode->vdisplay > maxY) 782 mode->status = MODE_VIRTUAL_Y; 783 } 784 } 785 EXPORT_SYMBOL(drm_mode_validate_size); 786 787 /** 788 * drm_mode_validate_clocks - validate modes against clock limits 789 * @dev: DRM device 790 * @mode_list: list of modes to check 791 * @min: minimum clock rate array 792 * @max: maximum clock rate array 793 * @n_ranges: number of clock ranges (size of arrays) 794 * 795 * LOCKING: 796 * Caller must hold a lock protecting @mode_list. 797 * 798 * Some code may need to check a mode list against the clock limits of the 799 * device in question. This function walks the mode list, testing to make 800 * sure each mode falls within a given range (defined by @min and @max 801 * arrays) and sets @mode->status as needed. 802 */ 803 void drm_mode_validate_clocks(struct drm_device *dev, 804 struct list_head *mode_list, 805 int *min, int *max, int n_ranges) 806 { 807 struct drm_display_mode *mode; 808 int i; 809 810 list_for_each_entry(mode, mode_list, head) { 811 bool good = false; 812 for (i = 0; i < n_ranges; i++) { 813 if (mode->clock >= min[i] && mode->clock <= max[i]) { 814 good = true; 815 break; 816 } 817 } 818 if (!good) 819 mode->status = MODE_CLOCK_RANGE; 820 } 821 } 822 EXPORT_SYMBOL(drm_mode_validate_clocks); 823 824 /** 825 * drm_mode_prune_invalid - remove invalid modes from mode list 826 * @dev: DRM device 827 * @mode_list: list of modes to check 828 * @verbose: be verbose about it 829 * 830 * LOCKING: 831 * Caller must hold a lock protecting @mode_list. 832 * 833 * Once mode list generation is complete, a caller can use this routine to 834 * remove invalid modes from a mode list. If any of the modes have a 835 * status other than %MODE_OK, they are removed from @mode_list and freed. 836 */ 837 void drm_mode_prune_invalid(struct drm_device *dev, 838 struct list_head *mode_list, bool verbose) 839 { 840 struct drm_display_mode *mode, *t; 841 842 list_for_each_entry_safe(mode, t, mode_list, head) { 843 if (mode->status != MODE_OK) { 844 list_del(&mode->head); 845 if (verbose) { 846 drm_mode_debug_printmodeline(mode); 847 DRM_DEBUG_KMS("Not using %s mode %d\n", 848 mode->name, mode->status); 849 } 850 drm_mode_destroy(dev, mode); 851 } 852 } 853 } 854 EXPORT_SYMBOL(drm_mode_prune_invalid); 855 856 /** 857 * drm_mode_compare - compare modes for favorability 858 * @lh_a: list_head for first mode 859 * @lh_b: list_head for second mode 860 * 861 * LOCKING: 862 * None. 863 * 864 * Compare two modes, given by @lh_a and @lh_b, returning a value indicating 865 * which is better. 866 * 867 * RETURNS: 868 * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or 869 * positive if @lh_b is better than @lh_a. 870 */ 871 static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b) 872 { 873 struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head); 874 struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head); 875 int diff; 876 877 diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) - 878 ((a->type & DRM_MODE_TYPE_PREFERRED) != 0); 879 if (diff) 880 return diff; 881 diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay; 882 if (diff) 883 return diff; 884 diff = b->clock - a->clock; 885 return diff; 886 } 887 888 /* FIXME: what we don't have a list sort function? */ 889 /* list sort from Mark J Roberts (mjr@znex.org) */ 890 void list_sort(struct list_head *head, 891 int (*cmp)(struct list_head *a, struct list_head *b)) 892 { 893 struct list_head *p, *q, *e, *list, *tail, *oldhead; 894 int insize, nmerges, psize, qsize, i; 895 896 list = head->next; 897 list_del(head); 898 insize = 1; 899 for (;;) { 900 p = oldhead = list; 901 list = tail = NULL; 902 nmerges = 0; 903 904 while (p) { 905 nmerges++; 906 q = p; 907 psize = 0; 908 for (i = 0; i < insize; i++) { 909 psize++; 910 q = q->next == oldhead ? NULL : q->next; 911 if (!q) 912 break; 913 } 914 915 qsize = insize; 916 while (psize > 0 || (qsize > 0 && q)) { 917 if (!psize) { 918 e = q; 919 q = q->next; 920 qsize--; 921 if (q == oldhead) 922 q = NULL; 923 } else if (!qsize || !q) { 924 e = p; 925 p = p->next; 926 psize--; 927 if (p == oldhead) 928 p = NULL; 929 } else if (cmp(p, q) <= 0) { 930 e = p; 931 p = p->next; 932 psize--; 933 if (p == oldhead) 934 p = NULL; 935 } else { 936 e = q; 937 q = q->next; 938 qsize--; 939 if (q == oldhead) 940 q = NULL; 941 } 942 if (tail) 943 tail->next = e; 944 else 945 list = e; 946 e->prev = tail; 947 tail = e; 948 } 949 p = q; 950 } 951 952 tail->next = list; 953 list->prev = tail; 954 955 if (nmerges <= 1) 956 break; 957 958 insize *= 2; 959 } 960 961 head->next = list; 962 head->prev = list->prev; 963 list->prev->next = head; 964 list->prev = head; 965 } 966 967 /** 968 * drm_mode_sort - sort mode list 969 * @mode_list: list to sort 970 * 971 * LOCKING: 972 * Caller must hold a lock protecting @mode_list. 973 * 974 * Sort @mode_list by favorability, putting good modes first. 975 */ 976 void drm_mode_sort(struct list_head *mode_list) 977 { 978 list_sort(mode_list, drm_mode_compare); 979 } 980 EXPORT_SYMBOL(drm_mode_sort); 981 982 /** 983 * drm_mode_connector_list_update - update the mode list for the connector 984 * @connector: the connector to update 985 * 986 * LOCKING: 987 * Caller must hold a lock protecting @mode_list. 988 * 989 * This moves the modes from the @connector probed_modes list 990 * to the actual mode list. It compares the probed mode against the current 991 * list and only adds different modes. All modes unverified after this point 992 * will be removed by the prune invalid modes. 993 */ 994 void drm_mode_connector_list_update(struct drm_connector *connector) 995 { 996 struct drm_display_mode *mode; 997 struct drm_display_mode *pmode, *pt; 998 int found_it; 999 1000 list_for_each_entry_safe(pmode, pt, &connector->probed_modes, 1001 head) { 1002 found_it = 0; 1003 /* go through current modes checking for the new probed mode */ 1004 list_for_each_entry(mode, &connector->modes, head) { 1005 if (drm_mode_equal(pmode, mode)) { 1006 found_it = 1; 1007 /* if equal delete the probed mode */ 1008 mode->status = pmode->status; 1009 /* Merge type bits together */ 1010 mode->type |= pmode->type; 1011 list_del(&pmode->head); 1012 drm_mode_destroy(connector->dev, pmode); 1013 break; 1014 } 1015 } 1016 1017 if (!found_it) { 1018 list_move_tail(&pmode->head, &connector->modes); 1019 } 1020 } 1021 } 1022 EXPORT_SYMBOL(drm_mode_connector_list_update); 1023