drm_modes.c 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077
  1. /*
  2. * Copyright © 1997-2003 by The XFree86 Project, Inc.
  3. * Copyright © 2007 Dave Airlie
  4. * Copyright © 2007-2008 Intel Corporation
  5. * Jesse Barnes <jesse.barnes@intel.com>
  6. * Copyright 2005-2006 Luc Verhaegen
  7. * Copyright (c) 2001, Andy Ritger aritger@nvidia.com
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  25. * OTHER DEALINGS IN THE SOFTWARE.
  26. *
  27. * Except as contained in this notice, the name of the copyright holder(s)
  28. * and author(s) shall not be used in advertising or otherwise to promote
  29. * the sale, use or other dealings in this Software without prior written
  30. * authorization from the copyright holder(s) and author(s).
  31. */
  32. #include <linux/ctype.h>
  33. #include <linux/list.h>
  34. #include <linux/list_sort.h>
  35. #include <linux/export.h>
  36. #include <video/of_videomode.h>
  37. #include <video/videomode.h>
  38. #include <drm/drm_crtc.h>
  39. #include <drm/drm_device.h>
  40. #include <drm/drm_modes.h>
  41. #include <drm/drm_print.h>
  42. #include "drm_crtc_internal.h"
  43. /**
  44. * drm_mode_debug_printmodeline - print a mode to dmesg
  45. * @mode: mode to print
  46. *
  47. * Describe @mode using DRM_DEBUG.
  48. */
  49. void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
  50. {
  51. DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  52. }
  53. EXPORT_SYMBOL(drm_mode_debug_printmodeline);
  54. /**
  55. * drm_mode_create - create a new display mode
  56. * @dev: DRM device
  57. *
  58. * Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it
  59. * and return it.
  60. *
  61. * Returns:
  62. * Pointer to new mode on success, NULL on error.
  63. */
  64. struct drm_display_mode *drm_mode_create(struct drm_device *dev)
  65. {
  66. struct drm_display_mode *nmode;
  67. nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
  68. if (!nmode)
  69. return NULL;
  70. return nmode;
  71. }
  72. EXPORT_SYMBOL(drm_mode_create);
  73. /**
  74. * drm_mode_destroy - remove a mode
  75. * @dev: DRM device
  76. * @mode: mode to remove
  77. *
  78. * Release @mode's unique ID, then free it @mode structure itself using kfree.
  79. */
  80. void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
  81. {
  82. if (!mode)
  83. return;
  84. kfree(mode);
  85. }
  86. EXPORT_SYMBOL(drm_mode_destroy);
  87. /**
  88. * drm_mode_probed_add - add a mode to a connector's probed_mode list
  89. * @connector: connector the new mode
  90. * @mode: mode data
  91. *
  92. * Add @mode to @connector's probed_mode list for later use. This list should
  93. * then in a second step get filtered and all the modes actually supported by
  94. * the hardware moved to the @connector's modes list.
  95. */
  96. void drm_mode_probed_add(struct drm_connector *connector,
  97. struct drm_display_mode *mode)
  98. {
  99. WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
  100. list_add_tail(&mode->head, &connector->probed_modes);
  101. }
  102. EXPORT_SYMBOL(drm_mode_probed_add);
  103. /**
  104. * drm_cvt_mode -create a modeline based on the CVT algorithm
  105. * @dev: drm device
  106. * @hdisplay: hdisplay size
  107. * @vdisplay: vdisplay size
  108. * @vrefresh: vrefresh rate
  109. * @reduced: whether to use reduced blanking
  110. * @interlaced: whether to compute an interlaced mode
  111. * @margins: whether to add margins (borders)
  112. *
  113. * This function is called to generate the modeline based on CVT algorithm
  114. * according to the hdisplay, vdisplay, vrefresh.
  115. * It is based from the VESA(TM) Coordinated Video Timing Generator by
  116. * Graham Loveridge April 9, 2003 available at
  117. * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
  118. *
  119. * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
  120. * What I have done is to translate it by using integer calculation.
  121. *
  122. * Returns:
  123. * The modeline based on the CVT algorithm stored in a drm_display_mode object.
  124. * The display mode object is allocated with drm_mode_create(). Returns NULL
  125. * when no mode could be allocated.
  126. */
  127. struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
  128. int vdisplay, int vrefresh,
  129. bool reduced, bool interlaced, bool margins)
  130. {
  131. #define HV_FACTOR 1000
  132. /* 1) top/bottom margin size (% of height) - default: 1.8, */
  133. #define CVT_MARGIN_PERCENTAGE 18
  134. /* 2) character cell horizontal granularity (pixels) - default 8 */
  135. #define CVT_H_GRANULARITY 8
  136. /* 3) Minimum vertical porch (lines) - default 3 */
  137. #define CVT_MIN_V_PORCH 3
  138. /* 4) Minimum number of vertical back porch lines - default 6 */
  139. #define CVT_MIN_V_BPORCH 6
  140. /* Pixel Clock step (kHz) */
  141. #define CVT_CLOCK_STEP 250
  142. struct drm_display_mode *drm_mode;
  143. unsigned int vfieldrate, hperiod;
  144. int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
  145. int interlace;
  146. u64 tmp;
  147. if (!hdisplay || !vdisplay)
  148. return NULL;
  149. /* allocate the drm_display_mode structure. If failure, we will
  150. * return directly
  151. */
  152. drm_mode = drm_mode_create(dev);
  153. if (!drm_mode)
  154. return NULL;
  155. /* the CVT default refresh rate is 60Hz */
  156. if (!vrefresh)
  157. vrefresh = 60;
  158. /* the required field fresh rate */
  159. if (interlaced)
  160. vfieldrate = vrefresh * 2;
  161. else
  162. vfieldrate = vrefresh;
  163. /* horizontal pixels */
  164. hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY);
  165. /* determine the left&right borders */
  166. hmargin = 0;
  167. if (margins) {
  168. hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
  169. hmargin -= hmargin % CVT_H_GRANULARITY;
  170. }
  171. /* find the total active pixels */
  172. drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin;
  173. /* find the number of lines per field */
  174. if (interlaced)
  175. vdisplay_rnd = vdisplay / 2;
  176. else
  177. vdisplay_rnd = vdisplay;
  178. /* find the top & bottom borders */
  179. vmargin = 0;
  180. if (margins)
  181. vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
  182. drm_mode->vdisplay = vdisplay + 2 * vmargin;
  183. /* Interlaced */
  184. if (interlaced)
  185. interlace = 1;
  186. else
  187. interlace = 0;
  188. /* Determine VSync Width from aspect ratio */
  189. if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay))
  190. vsync = 4;
  191. else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay))
  192. vsync = 5;
  193. else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay))
  194. vsync = 6;
  195. else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay))
  196. vsync = 7;
  197. else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay))
  198. vsync = 7;
  199. else /* custom */
  200. vsync = 10;
  201. if (!reduced) {
  202. /* simplify the GTF calculation */
  203. /* 4) Minimum time of vertical sync + back porch interval (µs)
  204. * default 550.0
  205. */
  206. int tmp1, tmp2;
  207. #define CVT_MIN_VSYNC_BP 550
  208. /* 3) Nominal HSync width (% of line period) - default 8 */
  209. #define CVT_HSYNC_PERCENTAGE 8
  210. unsigned int hblank_percentage;
  211. int vsyncandback_porch, __maybe_unused vback_porch, hblank;
  212. /* estimated the horizontal period */
  213. tmp1 = HV_FACTOR * 1000000 -
  214. CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate;
  215. tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 +
  216. interlace;
  217. hperiod = tmp1 * 2 / (tmp2 * vfieldrate);
  218. tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1;
  219. /* 9. Find number of lines in sync + backporch */
  220. if (tmp1 < (vsync + CVT_MIN_V_PORCH))
  221. vsyncandback_porch = vsync + CVT_MIN_V_PORCH;
  222. else
  223. vsyncandback_porch = tmp1;
  224. /* 10. Find number of lines in back porch */
  225. vback_porch = vsyncandback_porch - vsync;
  226. drm_mode->vtotal = vdisplay_rnd + 2 * vmargin +
  227. vsyncandback_porch + CVT_MIN_V_PORCH;
  228. /* 5) Definition of Horizontal blanking time limitation */
  229. /* Gradient (%/kHz) - default 600 */
  230. #define CVT_M_FACTOR 600
  231. /* Offset (%) - default 40 */
  232. #define CVT_C_FACTOR 40
  233. /* Blanking time scaling factor - default 128 */
  234. #define CVT_K_FACTOR 128
  235. /* Scaling factor weighting - default 20 */
  236. #define CVT_J_FACTOR 20
  237. #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256)
  238. #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
  239. CVT_J_FACTOR)
  240. /* 12. Find ideal blanking duty cycle from formula */
  241. hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME *
  242. hperiod / 1000;
  243. /* 13. Blanking time */
  244. if (hblank_percentage < 20 * HV_FACTOR)
  245. hblank_percentage = 20 * HV_FACTOR;
  246. hblank = drm_mode->hdisplay * hblank_percentage /
  247. (100 * HV_FACTOR - hblank_percentage);
  248. hblank -= hblank % (2 * CVT_H_GRANULARITY);
  249. /* 14. find the total pixels per line */
  250. drm_mode->htotal = drm_mode->hdisplay + hblank;
  251. drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2;
  252. drm_mode->hsync_start = drm_mode->hsync_end -
  253. (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100;
  254. drm_mode->hsync_start += CVT_H_GRANULARITY -
  255. drm_mode->hsync_start % CVT_H_GRANULARITY;
  256. /* fill the Vsync values */
  257. drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH;
  258. drm_mode->vsync_end = drm_mode->vsync_start + vsync;
  259. } else {
  260. /* Reduced blanking */
  261. /* Minimum vertical blanking interval time (µs)- default 460 */
  262. #define CVT_RB_MIN_VBLANK 460
  263. /* Fixed number of clocks for horizontal sync */
  264. #define CVT_RB_H_SYNC 32
  265. /* Fixed number of clocks for horizontal blanking */
  266. #define CVT_RB_H_BLANK 160
  267. /* Fixed number of lines for vertical front porch - default 3*/
  268. #define CVT_RB_VFPORCH 3
  269. int vbilines;
  270. int tmp1, tmp2;
  271. /* 8. Estimate Horizontal period. */
  272. tmp1 = HV_FACTOR * 1000000 -
  273. CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate;
  274. tmp2 = vdisplay_rnd + 2 * vmargin;
  275. hperiod = tmp1 / (tmp2 * vfieldrate);
  276. /* 9. Find number of lines in vertical blanking */
  277. vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1;
  278. /* 10. Check if vertical blanking is sufficient */
  279. if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH))
  280. vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH;
  281. /* 11. Find total number of lines in vertical field */
  282. drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines;
  283. /* 12. Find total number of pixels in a line */
  284. drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
  285. /* Fill in HSync values */
  286. drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
  287. drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC;
  288. /* Fill in VSync values */
  289. drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH;
  290. drm_mode->vsync_end = drm_mode->vsync_start + vsync;
  291. }
  292. /* 15/13. Find pixel clock frequency (kHz for xf86) */
  293. tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */
  294. tmp *= HV_FACTOR * 1000;
  295. do_div(tmp, hperiod);
  296. tmp -= drm_mode->clock % CVT_CLOCK_STEP;
  297. drm_mode->clock = tmp;
  298. /* 18/16. Find actual vertical frame frequency */
  299. /* ignore - just set the mode flag for interlaced */
  300. if (interlaced) {
  301. drm_mode->vtotal *= 2;
  302. drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
  303. }
  304. /* Fill the mode line name */
  305. drm_mode_set_name(drm_mode);
  306. if (reduced)
  307. drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC |
  308. DRM_MODE_FLAG_NVSYNC);
  309. else
  310. drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
  311. DRM_MODE_FLAG_NHSYNC);
  312. return drm_mode;
  313. }
  314. EXPORT_SYMBOL(drm_cvt_mode);
  315. /**
  316. * drm_gtf_mode_complex - create the modeline based on the full GTF algorithm
  317. * @dev: drm device
  318. * @hdisplay: hdisplay size
  319. * @vdisplay: vdisplay size
  320. * @vrefresh: vrefresh rate.
  321. * @interlaced: whether to compute an interlaced mode
  322. * @margins: desired margin (borders) size
  323. * @GTF_M: extended GTF formula parameters
  324. * @GTF_2C: extended GTF formula parameters
  325. * @GTF_K: extended GTF formula parameters
  326. * @GTF_2J: extended GTF formula parameters
  327. *
  328. * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
  329. * in here multiplied by two. For a C of 40, pass in 80.
  330. *
  331. * Returns:
  332. * The modeline based on the full GTF algorithm stored in a drm_display_mode object.
  333. * The display mode object is allocated with drm_mode_create(). Returns NULL
  334. * when no mode could be allocated.
  335. */
  336. struct drm_display_mode *
  337. drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
  338. int vrefresh, bool interlaced, int margins,
  339. int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
  340. { /* 1) top/bottom margin size (% of height) - default: 1.8, */
  341. #define GTF_MARGIN_PERCENTAGE 18
  342. /* 2) character cell horizontal granularity (pixels) - default 8 */
  343. #define GTF_CELL_GRAN 8
  344. /* 3) Minimum vertical porch (lines) - default 3 */
  345. #define GTF_MIN_V_PORCH 1
  346. /* width of vsync in lines */
  347. #define V_SYNC_RQD 3
  348. /* width of hsync as % of total line */
  349. #define H_SYNC_PERCENT 8
  350. /* min time of vsync + back porch (microsec) */
  351. #define MIN_VSYNC_PLUS_BP 550
  352. /* C' and M' are part of the Blanking Duty Cycle computation */
  353. #define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
  354. #define GTF_M_PRIME (GTF_K * GTF_M / 256)
  355. struct drm_display_mode *drm_mode;
  356. unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
  357. int top_margin, bottom_margin;
  358. int interlace;
  359. unsigned int hfreq_est;
  360. int vsync_plus_bp, __maybe_unused vback_porch;
  361. unsigned int vtotal_lines, __maybe_unused vfieldrate_est;
  362. unsigned int __maybe_unused hperiod;
  363. unsigned int vfield_rate, __maybe_unused vframe_rate;
  364. int left_margin, right_margin;
  365. unsigned int total_active_pixels, ideal_duty_cycle;
  366. unsigned int hblank, total_pixels, pixel_freq;
  367. int hsync, hfront_porch, vodd_front_porch_lines;
  368. unsigned int tmp1, tmp2;
  369. if (!hdisplay || !vdisplay)
  370. return NULL;
  371. drm_mode = drm_mode_create(dev);
  372. if (!drm_mode)
  373. return NULL;
  374. /* 1. In order to give correct results, the number of horizontal
  375. * pixels requested is first processed to ensure that it is divisible
  376. * by the character size, by rounding it to the nearest character
  377. * cell boundary:
  378. */
  379. hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
  380. hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN;
  381. /* 2. If interlace is requested, the number of vertical lines assumed
  382. * by the calculation must be halved, as the computation calculates
  383. * the number of vertical lines per field.
  384. */
  385. if (interlaced)
  386. vdisplay_rnd = vdisplay / 2;
  387. else
  388. vdisplay_rnd = vdisplay;
  389. /* 3. Find the frame rate required: */
  390. if (interlaced)
  391. vfieldrate_rqd = vrefresh * 2;
  392. else
  393. vfieldrate_rqd = vrefresh;
  394. /* 4. Find number of lines in Top margin: */
  395. top_margin = 0;
  396. if (margins)
  397. top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
  398. 1000;
  399. /* 5. Find number of lines in bottom margin: */
  400. bottom_margin = top_margin;
  401. /* 6. If interlace is required, then set variable interlace: */
  402. if (interlaced)
  403. interlace = 1;
  404. else
  405. interlace = 0;
  406. /* 7. Estimate the Horizontal frequency */
  407. {
  408. tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500;
  409. tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) *
  410. 2 + interlace;
  411. hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1;
  412. }
  413. /* 8. Find the number of lines in V sync + back porch */
  414. /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
  415. vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000;
  416. vsync_plus_bp = (vsync_plus_bp + 500) / 1000;
  417. /* 9. Find the number of lines in V back porch alone: */
  418. vback_porch = vsync_plus_bp - V_SYNC_RQD;
  419. /* 10. Find the total number of lines in Vertical field period: */
  420. vtotal_lines = vdisplay_rnd + top_margin + bottom_margin +
  421. vsync_plus_bp + GTF_MIN_V_PORCH;
  422. /* 11. Estimate the Vertical field frequency: */
  423. vfieldrate_est = hfreq_est / vtotal_lines;
  424. /* 12. Find the actual horizontal period: */
  425. hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines);
  426. /* 13. Find the actual Vertical field frequency: */
  427. vfield_rate = hfreq_est / vtotal_lines;
  428. /* 14. Find the Vertical frame frequency: */
  429. if (interlaced)
  430. vframe_rate = vfield_rate / 2;
  431. else
  432. vframe_rate = vfield_rate;
  433. /* 15. Find number of pixels in left margin: */
  434. if (margins)
  435. left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
  436. 1000;
  437. else
  438. left_margin = 0;
  439. /* 16.Find number of pixels in right margin: */
  440. right_margin = left_margin;
  441. /* 17.Find total number of active pixels in image and left and right */
  442. total_active_pixels = hdisplay_rnd + left_margin + right_margin;
  443. /* 18.Find the ideal blanking duty cycle from blanking duty cycle */
  444. ideal_duty_cycle = GTF_C_PRIME * 1000 -
  445. (GTF_M_PRIME * 1000000 / hfreq_est);
  446. /* 19.Find the number of pixels in the blanking time to the nearest
  447. * double character cell: */
  448. hblank = total_active_pixels * ideal_duty_cycle /
  449. (100000 - ideal_duty_cycle);
  450. hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN);
  451. hblank = hblank * 2 * GTF_CELL_GRAN;
  452. /* 20.Find total number of pixels: */
  453. total_pixels = total_active_pixels + hblank;
  454. /* 21.Find pixel clock frequency: */
  455. pixel_freq = total_pixels * hfreq_est / 1000;
  456. /* Stage 1 computations are now complete; I should really pass
  457. * the results to another function and do the Stage 2 computations,
  458. * but I only need a few more values so I'll just append the
  459. * computations here for now */
  460. /* 17. Find the number of pixels in the horizontal sync period: */
  461. hsync = H_SYNC_PERCENT * total_pixels / 100;
  462. hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
  463. hsync = hsync * GTF_CELL_GRAN;
  464. /* 18. Find the number of pixels in horizontal front porch period */
  465. hfront_porch = hblank / 2 - hsync;
  466. /* 36. Find the number of lines in the odd front porch period: */
  467. vodd_front_porch_lines = GTF_MIN_V_PORCH ;
  468. /* finally, pack the results in the mode struct */
  469. drm_mode->hdisplay = hdisplay_rnd;
  470. drm_mode->hsync_start = hdisplay_rnd + hfront_porch;
  471. drm_mode->hsync_end = drm_mode->hsync_start + hsync;
  472. drm_mode->htotal = total_pixels;
  473. drm_mode->vdisplay = vdisplay_rnd;
  474. drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines;
  475. drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD;
  476. drm_mode->vtotal = vtotal_lines;
  477. drm_mode->clock = pixel_freq;
  478. if (interlaced) {
  479. drm_mode->vtotal *= 2;
  480. drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
  481. }
  482. drm_mode_set_name(drm_mode);
  483. if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40)
  484. drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
  485. else
  486. drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC;
  487. return drm_mode;
  488. }
  489. EXPORT_SYMBOL(drm_gtf_mode_complex);
  490. /**
  491. * drm_gtf_mode - create the modeline based on the GTF algorithm
  492. * @dev: drm device
  493. * @hdisplay: hdisplay size
  494. * @vdisplay: vdisplay size
  495. * @vrefresh: vrefresh rate.
  496. * @interlaced: whether to compute an interlaced mode
  497. * @margins: desired margin (borders) size
  498. *
  499. * return the modeline based on GTF algorithm
  500. *
  501. * This function is to create the modeline based on the GTF algorithm.
  502. * Generalized Timing Formula is derived from:
  503. *
  504. * GTF Spreadsheet by Andy Morrish (1/5/97)
  505. * available at https://www.vesa.org
  506. *
  507. * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
  508. * What I have done is to translate it by using integer calculation.
  509. * I also refer to the function of fb_get_mode in the file of
  510. * drivers/video/fbmon.c
  511. *
  512. * Standard GTF parameters::
  513. *
  514. * M = 600
  515. * C = 40
  516. * K = 128
  517. * J = 20
  518. *
  519. * Returns:
  520. * The modeline based on the GTF algorithm stored in a drm_display_mode object.
  521. * The display mode object is allocated with drm_mode_create(). Returns NULL
  522. * when no mode could be allocated.
  523. */
  524. struct drm_display_mode *
  525. drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
  526. bool interlaced, int margins)
  527. {
  528. return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh,
  529. interlaced, margins,
  530. 600, 40 * 2, 128, 20 * 2);
  531. }
  532. EXPORT_SYMBOL(drm_gtf_mode);
  533. #ifdef CONFIG_VIDEOMODE_HELPERS
  534. /**
  535. * drm_display_mode_from_videomode - fill in @dmode using @vm,
  536. * @vm: videomode structure to use as source
  537. * @dmode: drm_display_mode structure to use as destination
  538. *
  539. * Fills out @dmode using the display mode specified in @vm.
  540. */
  541. void drm_display_mode_from_videomode(const struct videomode *vm,
  542. struct drm_display_mode *dmode)
  543. {
  544. dmode->hdisplay = vm->hactive;
  545. dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
  546. dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
  547. dmode->htotal = dmode->hsync_end + vm->hback_porch;
  548. dmode->vdisplay = vm->vactive;
  549. dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
  550. dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
  551. dmode->vtotal = dmode->vsync_end + vm->vback_porch;
  552. dmode->clock = vm->pixelclock / 1000;
  553. dmode->flags = 0;
  554. if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
  555. dmode->flags |= DRM_MODE_FLAG_PHSYNC;
  556. else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
  557. dmode->flags |= DRM_MODE_FLAG_NHSYNC;
  558. if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
  559. dmode->flags |= DRM_MODE_FLAG_PVSYNC;
  560. else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
  561. dmode->flags |= DRM_MODE_FLAG_NVSYNC;
  562. if (vm->flags & DISPLAY_FLAGS_INTERLACED)
  563. dmode->flags |= DRM_MODE_FLAG_INTERLACE;
  564. if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
  565. dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
  566. if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
  567. dmode->flags |= DRM_MODE_FLAG_DBLCLK;
  568. drm_mode_set_name(dmode);
  569. }
  570. EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
  571. /**
  572. * drm_display_mode_to_videomode - fill in @vm using @dmode,
  573. * @dmode: drm_display_mode structure to use as source
  574. * @vm: videomode structure to use as destination
  575. *
  576. * Fills out @vm using the display mode specified in @dmode.
  577. */
  578. void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
  579. struct videomode *vm)
  580. {
  581. vm->hactive = dmode->hdisplay;
  582. vm->hfront_porch = dmode->hsync_start - dmode->hdisplay;
  583. vm->hsync_len = dmode->hsync_end - dmode->hsync_start;
  584. vm->hback_porch = dmode->htotal - dmode->hsync_end;
  585. vm->vactive = dmode->vdisplay;
  586. vm->vfront_porch = dmode->vsync_start - dmode->vdisplay;
  587. vm->vsync_len = dmode->vsync_end - dmode->vsync_start;
  588. vm->vback_porch = dmode->vtotal - dmode->vsync_end;
  589. vm->pixelclock = dmode->clock * 1000;
  590. vm->flags = 0;
  591. if (dmode->flags & DRM_MODE_FLAG_PHSYNC)
  592. vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
  593. else if (dmode->flags & DRM_MODE_FLAG_NHSYNC)
  594. vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
  595. if (dmode->flags & DRM_MODE_FLAG_PVSYNC)
  596. vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
  597. else if (dmode->flags & DRM_MODE_FLAG_NVSYNC)
  598. vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
  599. if (dmode->flags & DRM_MODE_FLAG_INTERLACE)
  600. vm->flags |= DISPLAY_FLAGS_INTERLACED;
  601. if (dmode->flags & DRM_MODE_FLAG_DBLSCAN)
  602. vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
  603. if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
  604. vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
  605. }
  606. EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
  607. /**
  608. * drm_bus_flags_from_videomode - extract information about pixelclk and
  609. * DE polarity from videomode and store it in a separate variable
  610. * @vm: videomode structure to use
  611. * @bus_flags: information about pixelclk, sync and DE polarity will be stored
  612. * here
  613. *
  614. * Sets DRM_BUS_FLAG_DE_(LOW|HIGH), DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE
  615. * and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS
  616. * found in @vm
  617. */
  618. void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
  619. {
  620. *bus_flags = 0;
  621. if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
  622. *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
  623. if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
  624. *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
  625. if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
  626. *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
  627. if (vm->flags & DISPLAY_FLAGS_SYNC_NEGEDGE)
  628. *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
  629. if (vm->flags & DISPLAY_FLAGS_DE_LOW)
  630. *bus_flags |= DRM_BUS_FLAG_DE_LOW;
  631. if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
  632. *bus_flags |= DRM_BUS_FLAG_DE_HIGH;
  633. }
  634. EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode);
  635. #ifdef CONFIG_OF
  636. /**
  637. * of_get_drm_display_mode - get a drm_display_mode from devicetree
  638. * @np: device_node with the timing specification
  639. * @dmode: will be set to the return value
  640. * @bus_flags: information about pixelclk, sync and DE polarity
  641. * @index: index into the list of display timings in devicetree
  642. *
  643. * This function is expensive and should only be used, if only one mode is to be
  644. * read from DT. To get multiple modes start with of_get_display_timings and
  645. * work with that instead.
  646. *
  647. * Returns:
  648. * 0 on success, a negative errno code when no of videomode node was found.
  649. */
  650. int of_get_drm_display_mode(struct device_node *np,
  651. struct drm_display_mode *dmode, u32 *bus_flags,
  652. int index)
  653. {
  654. struct videomode vm;
  655. int ret;
  656. ret = of_get_videomode(np, &vm, index);
  657. if (ret)
  658. return ret;
  659. drm_display_mode_from_videomode(&vm, dmode);
  660. if (bus_flags)
  661. drm_bus_flags_from_videomode(&vm, bus_flags);
  662. pr_debug("%pOF: got %dx%d display mode\n",
  663. np, vm.hactive, vm.vactive);
  664. drm_mode_debug_printmodeline(dmode);
  665. return 0;
  666. }
  667. EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
  668. #endif /* CONFIG_OF */
  669. #endif /* CONFIG_VIDEOMODE_HELPERS */
  670. /**
  671. * drm_mode_set_name - set the name on a mode
  672. * @mode: name will be set in this mode
  673. *
  674. * Set the name of @mode to a standard format which is <hdisplay>x<vdisplay>
  675. * with an optional 'i' suffix for interlaced modes.
  676. */
  677. void drm_mode_set_name(struct drm_display_mode *mode)
  678. {
  679. bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
  680. snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
  681. mode->hdisplay, mode->vdisplay,
  682. interlaced ? "i" : "");
  683. }
  684. EXPORT_SYMBOL(drm_mode_set_name);
  685. /**
  686. * drm_mode_vrefresh - get the vrefresh of a mode
  687. * @mode: mode
  688. *
  689. * Returns:
  690. * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
  691. * value first if it is not yet set.
  692. */
  693. int drm_mode_vrefresh(const struct drm_display_mode *mode)
  694. {
  695. unsigned int num, den;
  696. if (mode->htotal == 0 || mode->vtotal == 0)
  697. return 0;
  698. num = mode->clock;
  699. den = mode->htotal * mode->vtotal;
  700. if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  701. num *= 2;
  702. if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
  703. den *= 2;
  704. if (mode->vscan > 1)
  705. den *= mode->vscan;
  706. return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
  707. }
  708. EXPORT_SYMBOL(drm_mode_vrefresh);
  709. /**
  710. * drm_mode_get_hv_timing - Fetches hdisplay/vdisplay for given mode
  711. * @mode: mode to query
  712. * @hdisplay: hdisplay value to fill in
  713. * @vdisplay: vdisplay value to fill in
  714. *
  715. * The vdisplay value will be doubled if the specified mode is a stereo mode of
  716. * the appropriate layout.
  717. */
  718. void drm_mode_get_hv_timing(const struct drm_display_mode *mode,
  719. int *hdisplay, int *vdisplay)
  720. {
  721. struct drm_display_mode adjusted = *mode;
  722. drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
  723. *hdisplay = adjusted.crtc_hdisplay;
  724. *vdisplay = adjusted.crtc_vdisplay;
  725. }
  726. EXPORT_SYMBOL(drm_mode_get_hv_timing);
  727. /**
  728. * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
  729. * @p: mode
  730. * @adjust_flags: a combination of adjustment flags
  731. *
  732. * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
  733. *
  734. * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
  735. * interlaced modes.
  736. * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
  737. * buffers containing two eyes (only adjust the timings when needed, eg. for
  738. * "frame packing" or "side by side full").
  739. * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
  740. * be performed for doublescan and vscan > 1 modes respectively.
  741. */
  742. void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
  743. {
  744. if (!p)
  745. return;
  746. p->crtc_clock = p->clock;
  747. p->crtc_hdisplay = p->hdisplay;
  748. p->crtc_hsync_start = p->hsync_start;
  749. p->crtc_hsync_end = p->hsync_end;
  750. p->crtc_htotal = p->htotal;
  751. p->crtc_hskew = p->hskew;
  752. p->crtc_vdisplay = p->vdisplay;
  753. p->crtc_vsync_start = p->vsync_start;
  754. p->crtc_vsync_end = p->vsync_end;
  755. p->crtc_vtotal = p->vtotal;
  756. if (p->flags & DRM_MODE_FLAG_INTERLACE) {
  757. if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
  758. p->crtc_vdisplay /= 2;
  759. p->crtc_vsync_start /= 2;
  760. p->crtc_vsync_end /= 2;
  761. p->crtc_vtotal /= 2;
  762. }
  763. }
  764. if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
  765. if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
  766. p->crtc_vdisplay *= 2;
  767. p->crtc_vsync_start *= 2;
  768. p->crtc_vsync_end *= 2;
  769. p->crtc_vtotal *= 2;
  770. }
  771. }
  772. if (!(adjust_flags & CRTC_NO_VSCAN)) {
  773. if (p->vscan > 1) {
  774. p->crtc_vdisplay *= p->vscan;
  775. p->crtc_vsync_start *= p->vscan;
  776. p->crtc_vsync_end *= p->vscan;
  777. p->crtc_vtotal *= p->vscan;
  778. }
  779. }
  780. if (adjust_flags & CRTC_STEREO_DOUBLE) {
  781. unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
  782. switch (layout) {
  783. case DRM_MODE_FLAG_3D_FRAME_PACKING:
  784. p->crtc_clock *= 2;
  785. p->crtc_vdisplay += p->crtc_vtotal;
  786. p->crtc_vsync_start += p->crtc_vtotal;
  787. p->crtc_vsync_end += p->crtc_vtotal;
  788. p->crtc_vtotal += p->crtc_vtotal;
  789. break;
  790. }
  791. }
  792. p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
  793. p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
  794. p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
  795. p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
  796. }
  797. EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  798. /**
  799. * drm_mode_copy - copy the mode
  800. * @dst: mode to overwrite
  801. * @src: mode to copy
  802. *
  803. * Copy an existing mode into another mode, preserving the object id and
  804. * list head of the destination mode.
  805. */
  806. void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
  807. {
  808. struct list_head head = dst->head;
  809. *dst = *src;
  810. dst->head = head;
  811. }
  812. EXPORT_SYMBOL(drm_mode_copy);
  813. /**
  814. * drm_mode_duplicate - allocate and duplicate an existing mode
  815. * @dev: drm_device to allocate the duplicated mode for
  816. * @mode: mode to duplicate
  817. *
  818. * Just allocate a new mode, copy the existing mode into it, and return
  819. * a pointer to it. Used to create new instances of established modes.
  820. *
  821. * Returns:
  822. * Pointer to duplicated mode on success, NULL on error.
  823. */
  824. struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
  825. const struct drm_display_mode *mode)
  826. {
  827. struct drm_display_mode *nmode;
  828. nmode = drm_mode_create(dev);
  829. if (!nmode)
  830. return NULL;
  831. drm_mode_copy(nmode, mode);
  832. return nmode;
  833. }
  834. EXPORT_SYMBOL(drm_mode_duplicate);
  835. static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
  836. const struct drm_display_mode *mode2)
  837. {
  838. return mode1->hdisplay == mode2->hdisplay &&
  839. mode1->hsync_start == mode2->hsync_start &&
  840. mode1->hsync_end == mode2->hsync_end &&
  841. mode1->htotal == mode2->htotal &&
  842. mode1->hskew == mode2->hskew &&
  843. mode1->vdisplay == mode2->vdisplay &&
  844. mode1->vsync_start == mode2->vsync_start &&
  845. mode1->vsync_end == mode2->vsync_end &&
  846. mode1->vtotal == mode2->vtotal &&
  847. mode1->vscan == mode2->vscan;
  848. }
  849. static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
  850. const struct drm_display_mode *mode2)
  851. {
  852. /*
  853. * do clock check convert to PICOS
  854. * so fb modes get matched the same
  855. */
  856. if (mode1->clock && mode2->clock)
  857. return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
  858. else
  859. return mode1->clock == mode2->clock;
  860. }
  861. static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
  862. const struct drm_display_mode *mode2)
  863. {
  864. return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
  865. (mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
  866. }
  867. static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
  868. const struct drm_display_mode *mode2)
  869. {
  870. return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
  871. (mode2->flags & DRM_MODE_FLAG_3D_MASK);
  872. }
  873. static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
  874. const struct drm_display_mode *mode2)
  875. {
  876. return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
  877. }
  878. /**
  879. * drm_mode_match - test modes for (partial) equality
  880. * @mode1: first mode
  881. * @mode2: second mode
  882. * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
  883. *
  884. * Check to see if @mode1 and @mode2 are equivalent.
  885. *
  886. * Returns:
  887. * True if the modes are (partially) equal, false otherwise.
  888. */
  889. bool drm_mode_match(const struct drm_display_mode *mode1,
  890. const struct drm_display_mode *mode2,
  891. unsigned int match_flags)
  892. {
  893. if (!mode1 && !mode2)
  894. return true;
  895. if (!mode1 || !mode2)
  896. return false;
  897. if (match_flags & DRM_MODE_MATCH_TIMINGS &&
  898. !drm_mode_match_timings(mode1, mode2))
  899. return false;
  900. if (match_flags & DRM_MODE_MATCH_CLOCK &&
  901. !drm_mode_match_clock(mode1, mode2))
  902. return false;
  903. if (match_flags & DRM_MODE_MATCH_FLAGS &&
  904. !drm_mode_match_flags(mode1, mode2))
  905. return false;
  906. if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
  907. !drm_mode_match_3d_flags(mode1, mode2))
  908. return false;
  909. if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
  910. !drm_mode_match_aspect_ratio(mode1, mode2))
  911. return false;
  912. return true;
  913. }
  914. EXPORT_SYMBOL(drm_mode_match);
  915. /**
  916. * drm_mode_equal - test modes for equality
  917. * @mode1: first mode
  918. * @mode2: second mode
  919. *
  920. * Check to see if @mode1 and @mode2 are equivalent.
  921. *
  922. * Returns:
  923. * True if the modes are equal, false otherwise.
  924. */
  925. bool drm_mode_equal(const struct drm_display_mode *mode1,
  926. const struct drm_display_mode *mode2)
  927. {
  928. return drm_mode_match(mode1, mode2,
  929. DRM_MODE_MATCH_TIMINGS |
  930. DRM_MODE_MATCH_CLOCK |
  931. DRM_MODE_MATCH_FLAGS |
  932. DRM_MODE_MATCH_3D_FLAGS|
  933. DRM_MODE_MATCH_ASPECT_RATIO);
  934. }
  935. EXPORT_SYMBOL(drm_mode_equal);
  936. /**
  937. * drm_mode_equal_no_clocks - test modes for equality
  938. * @mode1: first mode
  939. * @mode2: second mode
  940. *
  941. * Check to see if @mode1 and @mode2 are equivalent, but
  942. * don't check the pixel clocks.
  943. *
  944. * Returns:
  945. * True if the modes are equal, false otherwise.
  946. */
  947. bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
  948. const struct drm_display_mode *mode2)
  949. {
  950. return drm_mode_match(mode1, mode2,
  951. DRM_MODE_MATCH_TIMINGS |
  952. DRM_MODE_MATCH_FLAGS |
  953. DRM_MODE_MATCH_3D_FLAGS);
  954. }
  955. EXPORT_SYMBOL(drm_mode_equal_no_clocks);
  956. /**
  957. * drm_mode_equal_no_clocks_no_stereo - test modes for equality
  958. * @mode1: first mode
  959. * @mode2: second mode
  960. *
  961. * Check to see if @mode1 and @mode2 are equivalent, but
  962. * don't check the pixel clocks nor the stereo layout.
  963. *
  964. * Returns:
  965. * True if the modes are equal, false otherwise.
  966. */
  967. bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
  968. const struct drm_display_mode *mode2)
  969. {
  970. return drm_mode_match(mode1, mode2,
  971. DRM_MODE_MATCH_TIMINGS |
  972. DRM_MODE_MATCH_FLAGS);
  973. }
  974. EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
  975. static enum drm_mode_status
  976. drm_mode_validate_basic(const struct drm_display_mode *mode)
  977. {
  978. if (mode->type & ~DRM_MODE_TYPE_ALL)
  979. return MODE_BAD;
  980. if (mode->flags & ~DRM_MODE_FLAG_ALL)
  981. return MODE_BAD;
  982. if ((mode->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
  983. return MODE_BAD;
  984. if (mode->clock == 0)
  985. return MODE_CLOCK_LOW;
  986. if (mode->hdisplay == 0 ||
  987. mode->hsync_start < mode->hdisplay ||
  988. mode->hsync_end < mode->hsync_start ||
  989. mode->htotal < mode->hsync_end)
  990. return MODE_H_ILLEGAL;
  991. if (mode->vdisplay == 0 ||
  992. mode->vsync_start < mode->vdisplay ||
  993. mode->vsync_end < mode->vsync_start ||
  994. mode->vtotal < mode->vsync_end)
  995. return MODE_V_ILLEGAL;
  996. return MODE_OK;
  997. }
  998. /**
  999. * drm_mode_validate_driver - make sure the mode is somewhat sane
  1000. * @dev: drm device
  1001. * @mode: mode to check
  1002. *
  1003. * First do basic validation on the mode, and then allow the driver
  1004. * to check for device/driver specific limitations via the optional
  1005. * &drm_mode_config_helper_funcs.mode_valid hook.
  1006. *
  1007. * Returns:
  1008. * The mode status
  1009. */
  1010. enum drm_mode_status
  1011. drm_mode_validate_driver(struct drm_device *dev,
  1012. const struct drm_display_mode *mode)
  1013. {
  1014. enum drm_mode_status status;
  1015. status = drm_mode_validate_basic(mode);
  1016. if (status != MODE_OK)
  1017. return status;
  1018. if (dev->mode_config.funcs->mode_valid)
  1019. return dev->mode_config.funcs->mode_valid(dev, mode);
  1020. else
  1021. return MODE_OK;
  1022. }
  1023. EXPORT_SYMBOL(drm_mode_validate_driver);
  1024. /**
  1025. * drm_mode_validate_size - make sure modes adhere to size constraints
  1026. * @mode: mode to check
  1027. * @maxX: maximum width
  1028. * @maxY: maximum height
  1029. *
  1030. * This function is a helper which can be used to validate modes against size
  1031. * limitations of the DRM device/connector. If a mode is too big its status
  1032. * member is updated with the appropriate validation failure code. The list
  1033. * itself is not changed.
  1034. *
  1035. * Returns:
  1036. * The mode status
  1037. */
  1038. enum drm_mode_status
  1039. drm_mode_validate_size(const struct drm_display_mode *mode,
  1040. int maxX, int maxY)
  1041. {
  1042. if (maxX > 0 && mode->hdisplay > maxX)
  1043. return MODE_VIRTUAL_X;
  1044. if (maxY > 0 && mode->vdisplay > maxY)
  1045. return MODE_VIRTUAL_Y;
  1046. return MODE_OK;
  1047. }
  1048. EXPORT_SYMBOL(drm_mode_validate_size);
  1049. /**
  1050. * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
  1051. * @mode: mode to check
  1052. * @connector: drm connector under action
  1053. *
  1054. * This function is a helper which can be used to filter out any YCBCR420
  1055. * only mode, when the source doesn't support it.
  1056. *
  1057. * Returns:
  1058. * The mode status
  1059. */
  1060. enum drm_mode_status
  1061. drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
  1062. struct drm_connector *connector)
  1063. {
  1064. u8 vic = drm_match_cea_mode(mode);
  1065. enum drm_mode_status status = MODE_OK;
  1066. struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
  1067. if (test_bit(vic, hdmi->y420_vdb_modes)) {
  1068. if (!connector->ycbcr_420_allowed)
  1069. status = MODE_NO_420;
  1070. }
  1071. return status;
  1072. }
  1073. EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
  1074. #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
  1075. static const char * const drm_mode_status_names[] = {
  1076. MODE_STATUS(OK),
  1077. MODE_STATUS(HSYNC),
  1078. MODE_STATUS(VSYNC),
  1079. MODE_STATUS(H_ILLEGAL),
  1080. MODE_STATUS(V_ILLEGAL),
  1081. MODE_STATUS(BAD_WIDTH),
  1082. MODE_STATUS(NOMODE),
  1083. MODE_STATUS(NO_INTERLACE),
  1084. MODE_STATUS(NO_DBLESCAN),
  1085. MODE_STATUS(NO_VSCAN),
  1086. MODE_STATUS(MEM),
  1087. MODE_STATUS(VIRTUAL_X),
  1088. MODE_STATUS(VIRTUAL_Y),
  1089. MODE_STATUS(MEM_VIRT),
  1090. MODE_STATUS(NOCLOCK),
  1091. MODE_STATUS(CLOCK_HIGH),
  1092. MODE_STATUS(CLOCK_LOW),
  1093. MODE_STATUS(CLOCK_RANGE),
  1094. MODE_STATUS(BAD_HVALUE),
  1095. MODE_STATUS(BAD_VVALUE),
  1096. MODE_STATUS(BAD_VSCAN),
  1097. MODE_STATUS(HSYNC_NARROW),
  1098. MODE_STATUS(HSYNC_WIDE),
  1099. MODE_STATUS(HBLANK_NARROW),
  1100. MODE_STATUS(HBLANK_WIDE),
  1101. MODE_STATUS(VSYNC_NARROW),
  1102. MODE_STATUS(VSYNC_WIDE),
  1103. MODE_STATUS(VBLANK_NARROW),
  1104. MODE_STATUS(VBLANK_WIDE),
  1105. MODE_STATUS(PANEL),
  1106. MODE_STATUS(INTERLACE_WIDTH),
  1107. MODE_STATUS(ONE_WIDTH),
  1108. MODE_STATUS(ONE_HEIGHT),
  1109. MODE_STATUS(ONE_SIZE),
  1110. MODE_STATUS(NO_REDUCED),
  1111. MODE_STATUS(NO_STEREO),
  1112. MODE_STATUS(NO_420),
  1113. MODE_STATUS(STALE),
  1114. MODE_STATUS(BAD),
  1115. MODE_STATUS(ERROR),
  1116. };
  1117. #undef MODE_STATUS
  1118. const char *drm_get_mode_status_name(enum drm_mode_status status)
  1119. {
  1120. int index = status + 3;
  1121. if (WARN_ON(index < 0 || index >= ARRAY_SIZE(drm_mode_status_names)))
  1122. return "";
  1123. return drm_mode_status_names[index];
  1124. }
  1125. /**
  1126. * drm_mode_prune_invalid - remove invalid modes from mode list
  1127. * @dev: DRM device
  1128. * @mode_list: list of modes to check
  1129. * @verbose: be verbose about it
  1130. *
  1131. * This helper function can be used to prune a display mode list after
  1132. * validation has been completed. All modes whose status is not MODE_OK will be
  1133. * removed from the list, and if @verbose the status code and mode name is also
  1134. * printed to dmesg.
  1135. */
  1136. void drm_mode_prune_invalid(struct drm_device *dev,
  1137. struct list_head *mode_list, bool verbose)
  1138. {
  1139. struct drm_display_mode *mode, *t;
  1140. list_for_each_entry_safe(mode, t, mode_list, head) {
  1141. if (mode->status != MODE_OK) {
  1142. list_del(&mode->head);
  1143. if (verbose) {
  1144. drm_mode_debug_printmodeline(mode);
  1145. DRM_DEBUG_KMS("Not using %s mode: %s\n",
  1146. mode->name,
  1147. drm_get_mode_status_name(mode->status));
  1148. }
  1149. drm_mode_destroy(dev, mode);
  1150. }
  1151. }
  1152. }
  1153. EXPORT_SYMBOL(drm_mode_prune_invalid);
  1154. /**
  1155. * drm_mode_compare - compare modes for favorability
  1156. * @priv: unused
  1157. * @lh_a: list_head for first mode
  1158. * @lh_b: list_head for second mode
  1159. *
  1160. * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
  1161. * which is better.
  1162. *
  1163. * Returns:
  1164. * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
  1165. * positive if @lh_b is better than @lh_a.
  1166. */
  1167. static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b)
  1168. {
  1169. struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
  1170. struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
  1171. int diff;
  1172. diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
  1173. ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
  1174. if (diff)
  1175. return diff;
  1176. diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
  1177. if (diff)
  1178. return diff;
  1179. diff = drm_mode_vrefresh(b) - drm_mode_vrefresh(a);
  1180. if (diff)
  1181. return diff;
  1182. diff = b->clock - a->clock;
  1183. return diff;
  1184. }
  1185. /**
  1186. * drm_mode_sort - sort mode list
  1187. * @mode_list: list of drm_display_mode structures to sort
  1188. *
  1189. * Sort @mode_list by favorability, moving good modes to the head of the list.
  1190. */
  1191. void drm_mode_sort(struct list_head *mode_list)
  1192. {
  1193. list_sort(NULL, mode_list, drm_mode_compare);
  1194. }
  1195. EXPORT_SYMBOL(drm_mode_sort);
  1196. /**
  1197. * drm_connector_list_update - update the mode list for the connector
  1198. * @connector: the connector to update
  1199. *
  1200. * This moves the modes from the @connector probed_modes list
  1201. * to the actual mode list. It compares the probed mode against the current
  1202. * list and only adds different/new modes.
  1203. *
  1204. * This is just a helper functions doesn't validate any modes itself and also
  1205. * doesn't prune any invalid modes. Callers need to do that themselves.
  1206. */
  1207. void drm_connector_list_update(struct drm_connector *connector)
  1208. {
  1209. struct drm_display_mode *pmode, *pt;
  1210. WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
  1211. list_for_each_entry_safe(pmode, pt, &connector->probed_modes, head) {
  1212. struct drm_display_mode *mode;
  1213. bool found_it = false;
  1214. /* go through current modes checking for the new probed mode */
  1215. list_for_each_entry(mode, &connector->modes, head) {
  1216. if (!drm_mode_equal(pmode, mode))
  1217. continue;
  1218. found_it = true;
  1219. /*
  1220. * If the old matching mode is stale (ie. left over
  1221. * from a previous probe) just replace it outright.
  1222. * Otherwise just merge the type bits between all
  1223. * equal probed modes.
  1224. *
  1225. * If two probed modes are considered equal, pick the
  1226. * actual timings from the one that's marked as
  1227. * preferred (in case the match isn't 100%). If
  1228. * multiple or zero preferred modes are present, favor
  1229. * the mode added to the probed_modes list first.
  1230. */
  1231. if (mode->status == MODE_STALE) {
  1232. drm_mode_copy(mode, pmode);
  1233. } else if ((mode->type & DRM_MODE_TYPE_PREFERRED) == 0 &&
  1234. (pmode->type & DRM_MODE_TYPE_PREFERRED) != 0) {
  1235. pmode->type |= mode->type;
  1236. drm_mode_copy(mode, pmode);
  1237. } else {
  1238. mode->type |= pmode->type;
  1239. }
  1240. list_del(&pmode->head);
  1241. drm_mode_destroy(connector->dev, pmode);
  1242. break;
  1243. }
  1244. if (!found_it) {
  1245. list_move_tail(&pmode->head, &connector->modes);
  1246. }
  1247. }
  1248. }
  1249. EXPORT_SYMBOL(drm_connector_list_update);
  1250. static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
  1251. struct drm_cmdline_mode *mode)
  1252. {
  1253. unsigned int bpp;
  1254. if (str[0] != '-')
  1255. return -EINVAL;
  1256. str++;
  1257. bpp = simple_strtol(str, end_ptr, 10);
  1258. if (*end_ptr == str)
  1259. return -EINVAL;
  1260. mode->bpp = bpp;
  1261. mode->bpp_specified = true;
  1262. return 0;
  1263. }
  1264. static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
  1265. struct drm_cmdline_mode *mode)
  1266. {
  1267. unsigned int refresh;
  1268. if (str[0] != '@')
  1269. return -EINVAL;
  1270. str++;
  1271. refresh = simple_strtol(str, end_ptr, 10);
  1272. if (*end_ptr == str)
  1273. return -EINVAL;
  1274. mode->refresh = refresh;
  1275. mode->refresh_specified = true;
  1276. return 0;
  1277. }
  1278. static int drm_mode_parse_cmdline_extra(const char *str, int length,
  1279. bool freestanding,
  1280. const struct drm_connector *connector,
  1281. struct drm_cmdline_mode *mode)
  1282. {
  1283. int i;
  1284. for (i = 0; i < length; i++) {
  1285. switch (str[i]) {
  1286. case 'i':
  1287. if (freestanding)
  1288. return -EINVAL;
  1289. mode->interlace = true;
  1290. break;
  1291. case 'm':
  1292. if (freestanding)
  1293. return -EINVAL;
  1294. mode->margins = true;
  1295. break;
  1296. case 'D':
  1297. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1298. return -EINVAL;
  1299. if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
  1300. (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
  1301. mode->force = DRM_FORCE_ON;
  1302. else
  1303. mode->force = DRM_FORCE_ON_DIGITAL;
  1304. break;
  1305. case 'd':
  1306. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1307. return -EINVAL;
  1308. mode->force = DRM_FORCE_OFF;
  1309. break;
  1310. case 'e':
  1311. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1312. return -EINVAL;
  1313. mode->force = DRM_FORCE_ON;
  1314. break;
  1315. default:
  1316. return -EINVAL;
  1317. }
  1318. }
  1319. return 0;
  1320. }
  1321. static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
  1322. bool extras,
  1323. const struct drm_connector *connector,
  1324. struct drm_cmdline_mode *mode)
  1325. {
  1326. const char *str_start = str;
  1327. bool rb = false, cvt = false;
  1328. int xres = 0, yres = 0;
  1329. int remaining, i;
  1330. char *end_ptr;
  1331. xres = simple_strtol(str, &end_ptr, 10);
  1332. if (end_ptr == str)
  1333. return -EINVAL;
  1334. if (end_ptr[0] != 'x')
  1335. return -EINVAL;
  1336. end_ptr++;
  1337. str = end_ptr;
  1338. yres = simple_strtol(str, &end_ptr, 10);
  1339. if (end_ptr == str)
  1340. return -EINVAL;
  1341. remaining = length - (end_ptr - str_start);
  1342. if (remaining < 0)
  1343. return -EINVAL;
  1344. for (i = 0; i < remaining; i++) {
  1345. switch (end_ptr[i]) {
  1346. case 'M':
  1347. cvt = true;
  1348. break;
  1349. case 'R':
  1350. rb = true;
  1351. break;
  1352. default:
  1353. /*
  1354. * Try to pass that to our extras parsing
  1355. * function to handle the case where the
  1356. * extras are directly after the resolution
  1357. */
  1358. if (extras) {
  1359. int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
  1360. 1,
  1361. false,
  1362. connector,
  1363. mode);
  1364. if (ret)
  1365. return ret;
  1366. } else {
  1367. return -EINVAL;
  1368. }
  1369. }
  1370. }
  1371. mode->xres = xres;
  1372. mode->yres = yres;
  1373. mode->cvt = cvt;
  1374. mode->rb = rb;
  1375. return 0;
  1376. }
  1377. static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
  1378. {
  1379. const char *value;
  1380. char *endp;
  1381. /*
  1382. * delim must point to the '=', otherwise it is a syntax error and
  1383. * if delim points to the terminating zero, then delim + 1 wil point
  1384. * past the end of the string.
  1385. */
  1386. if (*delim != '=')
  1387. return -EINVAL;
  1388. value = delim + 1;
  1389. *int_ret = simple_strtol(value, &endp, 10);
  1390. /* Make sure we have parsed something */
  1391. if (endp == value)
  1392. return -EINVAL;
  1393. return 0;
  1394. }
  1395. static int drm_mode_parse_panel_orientation(const char *delim,
  1396. struct drm_cmdline_mode *mode)
  1397. {
  1398. const char *value;
  1399. if (*delim != '=')
  1400. return -EINVAL;
  1401. value = delim + 1;
  1402. delim = strchr(value, ',');
  1403. if (!delim)
  1404. delim = value + strlen(value);
  1405. if (!strncmp(value, "normal", delim - value))
  1406. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
  1407. else if (!strncmp(value, "upside_down", delim - value))
  1408. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
  1409. else if (!strncmp(value, "left_side_up", delim - value))
  1410. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
  1411. else if (!strncmp(value, "right_side_up", delim - value))
  1412. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
  1413. else
  1414. return -EINVAL;
  1415. return 0;
  1416. }
  1417. static int drm_mode_parse_cmdline_options(const char *str,
  1418. bool freestanding,
  1419. const struct drm_connector *connector,
  1420. struct drm_cmdline_mode *mode)
  1421. {
  1422. unsigned int deg, margin, rotation = 0;
  1423. const char *delim, *option, *sep;
  1424. option = str;
  1425. do {
  1426. delim = strchr(option, '=');
  1427. if (!delim) {
  1428. delim = strchr(option, ',');
  1429. if (!delim)
  1430. delim = option + strlen(option);
  1431. }
  1432. if (!strncmp(option, "rotate", delim - option)) {
  1433. if (drm_mode_parse_cmdline_int(delim, &deg))
  1434. return -EINVAL;
  1435. switch (deg) {
  1436. case 0:
  1437. rotation |= DRM_MODE_ROTATE_0;
  1438. break;
  1439. case 90:
  1440. rotation |= DRM_MODE_ROTATE_90;
  1441. break;
  1442. case 180:
  1443. rotation |= DRM_MODE_ROTATE_180;
  1444. break;
  1445. case 270:
  1446. rotation |= DRM_MODE_ROTATE_270;
  1447. break;
  1448. default:
  1449. return -EINVAL;
  1450. }
  1451. } else if (!strncmp(option, "reflect_x", delim - option)) {
  1452. rotation |= DRM_MODE_REFLECT_X;
  1453. } else if (!strncmp(option, "reflect_y", delim - option)) {
  1454. rotation |= DRM_MODE_REFLECT_Y;
  1455. } else if (!strncmp(option, "margin_right", delim - option)) {
  1456. if (drm_mode_parse_cmdline_int(delim, &margin))
  1457. return -EINVAL;
  1458. mode->tv_margins.right = margin;
  1459. } else if (!strncmp(option, "margin_left", delim - option)) {
  1460. if (drm_mode_parse_cmdline_int(delim, &margin))
  1461. return -EINVAL;
  1462. mode->tv_margins.left = margin;
  1463. } else if (!strncmp(option, "margin_top", delim - option)) {
  1464. if (drm_mode_parse_cmdline_int(delim, &margin))
  1465. return -EINVAL;
  1466. mode->tv_margins.top = margin;
  1467. } else if (!strncmp(option, "margin_bottom", delim - option)) {
  1468. if (drm_mode_parse_cmdline_int(delim, &margin))
  1469. return -EINVAL;
  1470. mode->tv_margins.bottom = margin;
  1471. } else if (!strncmp(option, "panel_orientation", delim - option)) {
  1472. if (drm_mode_parse_panel_orientation(delim, mode))
  1473. return -EINVAL;
  1474. } else {
  1475. return -EINVAL;
  1476. }
  1477. sep = strchr(delim, ',');
  1478. option = sep + 1;
  1479. } while (sep);
  1480. if (rotation && freestanding)
  1481. return -EINVAL;
  1482. if (!(rotation & DRM_MODE_ROTATE_MASK))
  1483. rotation |= DRM_MODE_ROTATE_0;
  1484. /* Make sure there is exactly one rotation defined */
  1485. if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
  1486. return -EINVAL;
  1487. mode->rotation_reflection = rotation;
  1488. return 0;
  1489. }
  1490. static const char * const drm_named_modes_whitelist[] = {
  1491. "NTSC",
  1492. "PAL",
  1493. };
  1494. /**
  1495. * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
  1496. * @mode_option: optional per connector mode option
  1497. * @connector: connector to parse modeline for
  1498. * @mode: preallocated drm_cmdline_mode structure to fill out
  1499. *
  1500. * This parses @mode_option command line modeline for modes and options to
  1501. * configure the connector. If @mode_option is NULL the default command line
  1502. * modeline in fb_mode_option will be parsed instead.
  1503. *
  1504. * This uses the same parameters as the fb modedb.c, except for an extra
  1505. * force-enable, force-enable-digital and force-disable bit at the end::
  1506. *
  1507. * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
  1508. *
  1509. * Additionals options can be provided following the mode, using a comma to
  1510. * separate each option. Valid options can be found in
  1511. * Documentation/fb/modedb.rst.
  1512. *
  1513. * The intermediate drm_cmdline_mode structure is required to store additional
  1514. * options from the command line modline like the force-enable/disable flag.
  1515. *
  1516. * Returns:
  1517. * True if a valid modeline has been parsed, false otherwise.
  1518. */
  1519. bool drm_mode_parse_command_line_for_connector(const char *mode_option,
  1520. const struct drm_connector *connector,
  1521. struct drm_cmdline_mode *mode)
  1522. {
  1523. const char *name;
  1524. bool freestanding = false, parse_extras = false;
  1525. unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
  1526. unsigned int mode_end = 0;
  1527. const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
  1528. const char *options_ptr = NULL;
  1529. char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
  1530. int i, len, ret;
  1531. memset(mode, 0, sizeof(*mode));
  1532. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
  1533. if (!mode_option)
  1534. return false;
  1535. name = mode_option;
  1536. /* Try to locate the bpp and refresh specifiers, if any */
  1537. bpp_ptr = strchr(name, '-');
  1538. if (bpp_ptr)
  1539. bpp_off = bpp_ptr - name;
  1540. refresh_ptr = strchr(name, '@');
  1541. if (refresh_ptr)
  1542. refresh_off = refresh_ptr - name;
  1543. /* Locate the start of named options */
  1544. options_ptr = strchr(name, ',');
  1545. if (options_ptr)
  1546. options_off = options_ptr - name;
  1547. /* Locate the end of the name / resolution, and parse it */
  1548. if (bpp_ptr) {
  1549. mode_end = bpp_off;
  1550. } else if (refresh_ptr) {
  1551. mode_end = refresh_off;
  1552. } else if (options_ptr) {
  1553. mode_end = options_off;
  1554. parse_extras = true;
  1555. } else {
  1556. mode_end = strlen(name);
  1557. parse_extras = true;
  1558. }
  1559. /* First check for a named mode */
  1560. for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
  1561. ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
  1562. if (ret == mode_end) {
  1563. if (refresh_ptr)
  1564. return false; /* named + refresh is invalid */
  1565. strcpy(mode->name, drm_named_modes_whitelist[i]);
  1566. mode->specified = true;
  1567. break;
  1568. }
  1569. }
  1570. /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
  1571. if (!mode->specified && isdigit(name[0])) {
  1572. ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
  1573. parse_extras,
  1574. connector,
  1575. mode);
  1576. if (ret)
  1577. return false;
  1578. mode->specified = true;
  1579. }
  1580. /* No mode? Check for freestanding extras and/or options */
  1581. if (!mode->specified) {
  1582. unsigned int len = strlen(mode_option);
  1583. if (bpp_ptr || refresh_ptr)
  1584. return false; /* syntax error */
  1585. if (len == 1 || (len >= 2 && mode_option[1] == ','))
  1586. extra_ptr = mode_option;
  1587. else
  1588. options_ptr = mode_option - 1;
  1589. freestanding = true;
  1590. }
  1591. if (bpp_ptr) {
  1592. ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
  1593. if (ret)
  1594. return false;
  1595. mode->bpp_specified = true;
  1596. }
  1597. if (refresh_ptr) {
  1598. ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
  1599. &refresh_end_ptr, mode);
  1600. if (ret)
  1601. return false;
  1602. mode->refresh_specified = true;
  1603. }
  1604. /*
  1605. * Locate the end of the bpp / refresh, and parse the extras
  1606. * if relevant
  1607. */
  1608. if (bpp_ptr && refresh_ptr)
  1609. extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
  1610. else if (bpp_ptr)
  1611. extra_ptr = bpp_end_ptr;
  1612. else if (refresh_ptr)
  1613. extra_ptr = refresh_end_ptr;
  1614. if (extra_ptr) {
  1615. if (options_ptr)
  1616. len = options_ptr - extra_ptr;
  1617. else
  1618. len = strlen(extra_ptr);
  1619. ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
  1620. connector, mode);
  1621. if (ret)
  1622. return false;
  1623. }
  1624. if (options_ptr) {
  1625. ret = drm_mode_parse_cmdline_options(options_ptr + 1,
  1626. freestanding,
  1627. connector, mode);
  1628. if (ret)
  1629. return false;
  1630. }
  1631. return true;
  1632. }
  1633. EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
  1634. /**
  1635. * drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
  1636. * @dev: DRM device to create the new mode for
  1637. * @cmd: input command line modeline
  1638. *
  1639. * Returns:
  1640. * Pointer to converted mode on success, NULL on error.
  1641. */
  1642. struct drm_display_mode *
  1643. drm_mode_create_from_cmdline_mode(struct drm_device *dev,
  1644. struct drm_cmdline_mode *cmd)
  1645. {
  1646. struct drm_display_mode *mode;
  1647. if (cmd->cvt)
  1648. mode = drm_cvt_mode(dev,
  1649. cmd->xres, cmd->yres,
  1650. cmd->refresh_specified ? cmd->refresh : 60,
  1651. cmd->rb, cmd->interlace,
  1652. cmd->margins);
  1653. else
  1654. mode = drm_gtf_mode(dev,
  1655. cmd->xres, cmd->yres,
  1656. cmd->refresh_specified ? cmd->refresh : 60,
  1657. cmd->interlace,
  1658. cmd->margins);
  1659. if (!mode)
  1660. return NULL;
  1661. mode->type |= DRM_MODE_TYPE_USERDEF;
  1662. /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
  1663. if (cmd->xres == 1366)
  1664. drm_mode_fixup_1366x768(mode);
  1665. drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
  1666. return mode;
  1667. }
  1668. EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
  1669. /**
  1670. * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
  1671. * @out: drm_mode_modeinfo struct to return to the user
  1672. * @in: drm_display_mode to use
  1673. *
  1674. * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
  1675. * the user.
  1676. */
  1677. void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
  1678. const struct drm_display_mode *in)
  1679. {
  1680. out->clock = in->clock;
  1681. out->hdisplay = in->hdisplay;
  1682. out->hsync_start = in->hsync_start;
  1683. out->hsync_end = in->hsync_end;
  1684. out->htotal = in->htotal;
  1685. out->hskew = in->hskew;
  1686. out->vdisplay = in->vdisplay;
  1687. out->vsync_start = in->vsync_start;
  1688. out->vsync_end = in->vsync_end;
  1689. out->vtotal = in->vtotal;
  1690. out->vscan = in->vscan;
  1691. out->vrefresh = drm_mode_vrefresh(in);
  1692. out->flags = in->flags;
  1693. out->type = in->type;
  1694. switch (in->picture_aspect_ratio) {
  1695. case HDMI_PICTURE_ASPECT_4_3:
  1696. out->flags |= DRM_MODE_FLAG_PIC_AR_4_3;
  1697. break;
  1698. case HDMI_PICTURE_ASPECT_16_9:
  1699. out->flags |= DRM_MODE_FLAG_PIC_AR_16_9;
  1700. break;
  1701. case HDMI_PICTURE_ASPECT_64_27:
  1702. out->flags |= DRM_MODE_FLAG_PIC_AR_64_27;
  1703. break;
  1704. case HDMI_PICTURE_ASPECT_256_135:
  1705. out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
  1706. break;
  1707. default:
  1708. WARN(1, "Invalid aspect ratio (0%x) on mode\n",
  1709. in->picture_aspect_ratio);
  1710. fallthrough;
  1711. case HDMI_PICTURE_ASPECT_NONE:
  1712. out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
  1713. break;
  1714. }
  1715. strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
  1716. out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
  1717. }
  1718. EXPORT_SYMBOL_GPL(drm_mode_convert_to_umode);
  1719. /**
  1720. * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode
  1721. * @dev: drm device
  1722. * @out: drm_display_mode to return to the user
  1723. * @in: drm_mode_modeinfo to use
  1724. *
  1725. * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
  1726. * the caller.
  1727. *
  1728. * Returns:
  1729. * Zero on success, negative errno on failure.
  1730. */
  1731. int drm_mode_convert_umode(struct drm_device *dev,
  1732. struct drm_display_mode *out,
  1733. const struct drm_mode_modeinfo *in)
  1734. {
  1735. if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
  1736. return -ERANGE;
  1737. out->clock = in->clock;
  1738. out->hdisplay = in->hdisplay;
  1739. out->hsync_start = in->hsync_start;
  1740. out->hsync_end = in->hsync_end;
  1741. out->htotal = in->htotal;
  1742. out->hskew = in->hskew;
  1743. out->vdisplay = in->vdisplay;
  1744. out->vsync_start = in->vsync_start;
  1745. out->vsync_end = in->vsync_end;
  1746. out->vtotal = in->vtotal;
  1747. out->vscan = in->vscan;
  1748. out->flags = in->flags;
  1749. /*
  1750. * Old xf86-video-vmware (possibly others too) used to
  1751. * leave 'type' unititialized. Just ignore any bits we
  1752. * don't like. It's a just hint after all, and more
  1753. * useful for the kernel->userspace direction anyway.
  1754. */
  1755. out->type = in->type & DRM_MODE_TYPE_ALL;
  1756. strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
  1757. out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
  1758. /* Clearing picture aspect ratio bits from out flags,
  1759. * as the aspect-ratio information is not stored in
  1760. * flags for kernel-mode, but in picture_aspect_ratio.
  1761. */
  1762. out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
  1763. switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
  1764. case DRM_MODE_FLAG_PIC_AR_4_3:
  1765. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
  1766. break;
  1767. case DRM_MODE_FLAG_PIC_AR_16_9:
  1768. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
  1769. break;
  1770. case DRM_MODE_FLAG_PIC_AR_64_27:
  1771. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27;
  1772. break;
  1773. case DRM_MODE_FLAG_PIC_AR_256_135:
  1774. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135;
  1775. break;
  1776. case DRM_MODE_FLAG_PIC_AR_NONE:
  1777. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
  1778. break;
  1779. default:
  1780. return -EINVAL;
  1781. }
  1782. out->status = drm_mode_validate_driver(dev, out);
  1783. if (out->status != MODE_OK)
  1784. return -EINVAL;
  1785. drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
  1786. return 0;
  1787. }
  1788. EXPORT_SYMBOL_GPL(drm_mode_convert_umode);
  1789. /**
  1790. * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
  1791. * output format
  1792. *
  1793. * @display: display under action
  1794. * @mode: video mode to be tested.
  1795. *
  1796. * Returns:
  1797. * true if the mode can be supported in YCBCR420 format
  1798. * false if not.
  1799. */
  1800. bool drm_mode_is_420_only(const struct drm_display_info *display,
  1801. const struct drm_display_mode *mode)
  1802. {
  1803. u8 vic = drm_match_cea_mode(mode);
  1804. return test_bit(vic, display->hdmi.y420_vdb_modes);
  1805. }
  1806. EXPORT_SYMBOL(drm_mode_is_420_only);
  1807. /**
  1808. * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
  1809. * output format also (along with RGB/YCBCR444/422)
  1810. *
  1811. * @display: display under action.
  1812. * @mode: video mode to be tested.
  1813. *
  1814. * Returns:
  1815. * true if the mode can be support YCBCR420 format
  1816. * false if not.
  1817. */
  1818. bool drm_mode_is_420_also(const struct drm_display_info *display,
  1819. const struct drm_display_mode *mode)
  1820. {
  1821. u8 vic = drm_match_cea_mode(mode);
  1822. return test_bit(vic, display->hdmi.y420_cmdb_modes);
  1823. }
  1824. EXPORT_SYMBOL(drm_mode_is_420_also);
  1825. /**
  1826. * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
  1827. * output format
  1828. *
  1829. * @display: display under action.
  1830. * @mode: video mode to be tested.
  1831. *
  1832. * Returns:
  1833. * true if the mode can be supported in YCBCR420 format
  1834. * false if not.
  1835. */
  1836. bool drm_mode_is_420(const struct drm_display_info *display,
  1837. const struct drm_display_mode *mode)
  1838. {
  1839. return drm_mode_is_420_only(display, mode) ||
  1840. drm_mode_is_420_also(display, mode);
  1841. }
  1842. EXPORT_SYMBOL(drm_mode_is_420);