drm_modes.c 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779
  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/export.h>
  34. #include <linux/fb.h> /* for KHZ2PICOS() */
  35. #include <linux/list.h>
  36. #include <linux/list_sort.h>
  37. #include <linux/of.h>
  38. #include <video/of_display_timing.h>
  39. #include <video/of_videomode.h>
  40. #include <video/videomode.h>
  41. #include <drm/drm_crtc.h>
  42. #include <drm/drm_device.h>
  43. #include <drm/drm_edid.h>
  44. #include <drm/drm_modes.h>
  45. #include <drm/drm_print.h>
  46. #include "drm_crtc_internal.h"
  47. /**
  48. * drm_mode_debug_printmodeline - print a mode to dmesg
  49. * @mode: mode to print
  50. *
  51. * Describe @mode using DRM_DEBUG.
  52. */
  53. void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
  54. {
  55. DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  56. }
  57. EXPORT_SYMBOL(drm_mode_debug_printmodeline);
  58. /**
  59. * drm_mode_create - create a new display mode
  60. * @dev: DRM device
  61. *
  62. * Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it
  63. * and return it.
  64. *
  65. * Returns:
  66. * Pointer to new mode on success, NULL on error.
  67. */
  68. struct drm_display_mode *drm_mode_create(struct drm_device *dev)
  69. {
  70. struct drm_display_mode *nmode;
  71. nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
  72. if (!nmode)
  73. return NULL;
  74. return nmode;
  75. }
  76. EXPORT_SYMBOL(drm_mode_create);
  77. /**
  78. * drm_mode_destroy - remove a mode
  79. * @dev: DRM device
  80. * @mode: mode to remove
  81. *
  82. * Release @mode's unique ID, then free it @mode structure itself using kfree.
  83. */
  84. void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
  85. {
  86. if (!mode)
  87. return;
  88. kfree(mode);
  89. }
  90. EXPORT_SYMBOL(drm_mode_destroy);
  91. /**
  92. * drm_mode_probed_add - add a mode to a connector's probed_mode list
  93. * @connector: connector the new mode
  94. * @mode: mode data
  95. *
  96. * Add @mode to @connector's probed_mode list for later use. This list should
  97. * then in a second step get filtered and all the modes actually supported by
  98. * the hardware moved to the @connector's modes list.
  99. */
  100. void drm_mode_probed_add(struct drm_connector *connector,
  101. struct drm_display_mode *mode)
  102. {
  103. WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
  104. list_add_tail(&mode->head, &connector->probed_modes);
  105. }
  106. EXPORT_SYMBOL(drm_mode_probed_add);
  107. enum drm_mode_analog {
  108. DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */
  109. DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */
  110. };
  111. /*
  112. * The timings come from:
  113. * - https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html
  114. * - https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html
  115. * - https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm
  116. */
  117. #define NTSC_LINE_DURATION_NS 63556U
  118. #define NTSC_LINES_NUMBER 525
  119. #define NTSC_HBLK_DURATION_TYP_NS 10900U
  120. #define NTSC_HBLK_DURATION_MIN_NS (NTSC_HBLK_DURATION_TYP_NS - 200)
  121. #define NTSC_HBLK_DURATION_MAX_NS (NTSC_HBLK_DURATION_TYP_NS + 200)
  122. #define NTSC_HACT_DURATION_TYP_NS (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_TYP_NS)
  123. #define NTSC_HACT_DURATION_MIN_NS (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MAX_NS)
  124. #define NTSC_HACT_DURATION_MAX_NS (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MIN_NS)
  125. #define NTSC_HFP_DURATION_TYP_NS 1500
  126. #define NTSC_HFP_DURATION_MIN_NS 1270
  127. #define NTSC_HFP_DURATION_MAX_NS 2220
  128. #define NTSC_HSLEN_DURATION_TYP_NS 4700
  129. #define NTSC_HSLEN_DURATION_MIN_NS (NTSC_HSLEN_DURATION_TYP_NS - 100)
  130. #define NTSC_HSLEN_DURATION_MAX_NS (NTSC_HSLEN_DURATION_TYP_NS + 100)
  131. #define NTSC_HBP_DURATION_TYP_NS 4700
  132. /*
  133. * I couldn't find the actual tolerance for the back porch, so let's
  134. * just reuse the sync length ones.
  135. */
  136. #define NTSC_HBP_DURATION_MIN_NS (NTSC_HBP_DURATION_TYP_NS - 100)
  137. #define NTSC_HBP_DURATION_MAX_NS (NTSC_HBP_DURATION_TYP_NS + 100)
  138. #define PAL_LINE_DURATION_NS 64000U
  139. #define PAL_LINES_NUMBER 625
  140. #define PAL_HACT_DURATION_TYP_NS 51950U
  141. #define PAL_HACT_DURATION_MIN_NS (PAL_HACT_DURATION_TYP_NS - 100)
  142. #define PAL_HACT_DURATION_MAX_NS (PAL_HACT_DURATION_TYP_NS + 400)
  143. #define PAL_HBLK_DURATION_TYP_NS (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_TYP_NS)
  144. #define PAL_HBLK_DURATION_MIN_NS (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MAX_NS)
  145. #define PAL_HBLK_DURATION_MAX_NS (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MIN_NS)
  146. #define PAL_HFP_DURATION_TYP_NS 1650
  147. #define PAL_HFP_DURATION_MIN_NS (PAL_HFP_DURATION_TYP_NS - 100)
  148. #define PAL_HFP_DURATION_MAX_NS (PAL_HFP_DURATION_TYP_NS + 400)
  149. #define PAL_HSLEN_DURATION_TYP_NS 4700
  150. #define PAL_HSLEN_DURATION_MIN_NS (PAL_HSLEN_DURATION_TYP_NS - 200)
  151. #define PAL_HSLEN_DURATION_MAX_NS (PAL_HSLEN_DURATION_TYP_NS + 200)
  152. #define PAL_HBP_DURATION_TYP_NS 5700
  153. #define PAL_HBP_DURATION_MIN_NS (PAL_HBP_DURATION_TYP_NS - 200)
  154. #define PAL_HBP_DURATION_MAX_NS (PAL_HBP_DURATION_TYP_NS + 200)
  155. struct analog_param_field {
  156. unsigned int even, odd;
  157. };
  158. #define PARAM_FIELD(_odd, _even) \
  159. { .even = _even, .odd = _odd }
  160. struct analog_param_range {
  161. unsigned int min, typ, max;
  162. };
  163. #define PARAM_RANGE(_min, _typ, _max) \
  164. { .min = _min, .typ = _typ, .max = _max }
  165. struct analog_parameters {
  166. unsigned int num_lines;
  167. unsigned int line_duration_ns;
  168. struct analog_param_range hact_ns;
  169. struct analog_param_range hfp_ns;
  170. struct analog_param_range hslen_ns;
  171. struct analog_param_range hbp_ns;
  172. struct analog_param_range hblk_ns;
  173. unsigned int bt601_hfp;
  174. struct analog_param_field vfp_lines;
  175. struct analog_param_field vslen_lines;
  176. struct analog_param_field vbp_lines;
  177. };
  178. #define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp, \
  179. _hslen, _hbp, _hblk, _bt601_hfp, _vfp, \
  180. _vslen, _vbp) \
  181. [_mode] = { \
  182. .num_lines = _lines, \
  183. .line_duration_ns = _line_dur, \
  184. .hact_ns = _hact, \
  185. .hfp_ns = _hfp, \
  186. .hslen_ns = _hslen, \
  187. .hbp_ns = _hbp, \
  188. .hblk_ns = _hblk, \
  189. .bt601_hfp = _bt601_hfp, \
  190. .vfp_lines = _vfp, \
  191. .vslen_lines = _vslen, \
  192. .vbp_lines = _vbp, \
  193. }
  194. static const struct analog_parameters tv_modes_parameters[] = {
  195. TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC,
  196. NTSC_LINES_NUMBER,
  197. NTSC_LINE_DURATION_NS,
  198. PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS,
  199. NTSC_HACT_DURATION_TYP_NS,
  200. NTSC_HACT_DURATION_MAX_NS),
  201. PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS,
  202. NTSC_HFP_DURATION_TYP_NS,
  203. NTSC_HFP_DURATION_MAX_NS),
  204. PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS,
  205. NTSC_HSLEN_DURATION_TYP_NS,
  206. NTSC_HSLEN_DURATION_MAX_NS),
  207. PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS,
  208. NTSC_HBP_DURATION_TYP_NS,
  209. NTSC_HBP_DURATION_MAX_NS),
  210. PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS,
  211. NTSC_HBLK_DURATION_TYP_NS,
  212. NTSC_HBLK_DURATION_MAX_NS),
  213. 16,
  214. PARAM_FIELD(3, 3),
  215. PARAM_FIELD(3, 3),
  216. PARAM_FIELD(16, 17)),
  217. TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL,
  218. PAL_LINES_NUMBER,
  219. PAL_LINE_DURATION_NS,
  220. PARAM_RANGE(PAL_HACT_DURATION_MIN_NS,
  221. PAL_HACT_DURATION_TYP_NS,
  222. PAL_HACT_DURATION_MAX_NS),
  223. PARAM_RANGE(PAL_HFP_DURATION_MIN_NS,
  224. PAL_HFP_DURATION_TYP_NS,
  225. PAL_HFP_DURATION_MAX_NS),
  226. PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS,
  227. PAL_HSLEN_DURATION_TYP_NS,
  228. PAL_HSLEN_DURATION_MAX_NS),
  229. PARAM_RANGE(PAL_HBP_DURATION_MIN_NS,
  230. PAL_HBP_DURATION_TYP_NS,
  231. PAL_HBP_DURATION_MAX_NS),
  232. PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS,
  233. PAL_HBLK_DURATION_TYP_NS,
  234. PAL_HBLK_DURATION_MAX_NS),
  235. 12,
  236. /*
  237. * The front porch is actually 6 short sync
  238. * pulses for the even field, and 5 for the
  239. * odd field. Each sync takes half a life so
  240. * the odd field front porch is shorter by
  241. * half a line.
  242. *
  243. * In progressive, we're supposed to use 6
  244. * pulses, so we're fine there
  245. */
  246. PARAM_FIELD(3, 2),
  247. /*
  248. * The vsync length is 5 long sync pulses,
  249. * each field taking half a line. We're
  250. * shorter for both fields by half a line.
  251. *
  252. * In progressive, we're supposed to use 5
  253. * pulses, so we're off by half
  254. * a line.
  255. *
  256. * In interlace, we're now off by half a line
  257. * for the even field and one line for the odd
  258. * field.
  259. */
  260. PARAM_FIELD(3, 3),
  261. /*
  262. * The back porch starts with post-equalizing
  263. * pulses, consisting in 5 short sync pulses
  264. * for the even field, 4 for the odd field. In
  265. * progressive, it's 5 short syncs.
  266. *
  267. * In progressive, we thus have 2.5 lines,
  268. * plus the 0.5 line we were missing
  269. * previously, so we should use 3 lines.
  270. *
  271. * In interlace, the even field is in the
  272. * exact same case than progressive. For the
  273. * odd field, we should be using 2 lines but
  274. * we're one line short, so we'll make up for
  275. * it here by using 3.
  276. *
  277. * The entire blanking area is supposed to
  278. * take 25 lines, so we also need to account
  279. * for the rest of the blanking area that
  280. * can't be in either the front porch or sync
  281. * period.
  282. */
  283. PARAM_FIELD(19, 20)),
  284. };
  285. static int fill_analog_mode(struct drm_device *dev,
  286. struct drm_display_mode *mode,
  287. const struct analog_parameters *params,
  288. unsigned long pixel_clock_hz,
  289. unsigned int hactive,
  290. unsigned int vactive,
  291. bool interlace)
  292. {
  293. unsigned long pixel_duration_ns = NSEC_PER_SEC / pixel_clock_hz;
  294. unsigned int htotal, vtotal;
  295. unsigned int max_hact, hact_duration_ns;
  296. unsigned int hblk, hblk_duration_ns;
  297. unsigned int hfp, hfp_duration_ns;
  298. unsigned int hslen, hslen_duration_ns;
  299. unsigned int hbp, hbp_duration_ns;
  300. unsigned int porches, porches_duration_ns;
  301. unsigned int vfp, vfp_min;
  302. unsigned int vbp, vbp_min;
  303. unsigned int vslen;
  304. bool bt601 = false;
  305. int porches_rem;
  306. u64 result;
  307. drm_dbg_kms(dev,
  308. "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
  309. hactive, vactive,
  310. interlace ? 'i' : 'p',
  311. params->num_lines,
  312. pixel_clock_hz / 1000);
  313. max_hact = params->hact_ns.max / pixel_duration_ns;
  314. if (pixel_clock_hz == 13500000 && hactive > max_hact && hactive <= 720) {
  315. drm_dbg_kms(dev, "Trying to generate a BT.601 mode. Disabling checks.\n");
  316. bt601 = true;
  317. }
  318. /*
  319. * Our pixel duration is going to be round down by the division,
  320. * so rounding up is probably going to introduce even more
  321. * deviation.
  322. */
  323. result = (u64)params->line_duration_ns * pixel_clock_hz;
  324. do_div(result, NSEC_PER_SEC);
  325. htotal = result;
  326. drm_dbg_kms(dev, "Total Horizontal Number of Pixels: %u\n", htotal);
  327. hact_duration_ns = hactive * pixel_duration_ns;
  328. if (!bt601 &&
  329. (hact_duration_ns < params->hact_ns.min ||
  330. hact_duration_ns > params->hact_ns.max)) {
  331. drm_err(dev, "Invalid horizontal active area duration: %uns (min: %u, max %u)\n",
  332. hact_duration_ns, params->hact_ns.min, params->hact_ns.max);
  333. return -EINVAL;
  334. }
  335. hblk = htotal - hactive;
  336. drm_dbg_kms(dev, "Horizontal Blanking Period: %u\n", hblk);
  337. hblk_duration_ns = hblk * pixel_duration_ns;
  338. if (!bt601 &&
  339. (hblk_duration_ns < params->hblk_ns.min ||
  340. hblk_duration_ns > params->hblk_ns.max)) {
  341. drm_err(dev, "Invalid horizontal blanking duration: %uns (min: %u, max %u)\n",
  342. hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max);
  343. return -EINVAL;
  344. }
  345. hslen = DIV_ROUND_UP(params->hslen_ns.typ, pixel_duration_ns);
  346. drm_dbg_kms(dev, "Horizontal Sync Period: %u\n", hslen);
  347. hslen_duration_ns = hslen * pixel_duration_ns;
  348. if (!bt601 &&
  349. (hslen_duration_ns < params->hslen_ns.min ||
  350. hslen_duration_ns > params->hslen_ns.max)) {
  351. drm_err(dev, "Invalid horizontal sync duration: %uns (min: %u, max %u)\n",
  352. hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max);
  353. return -EINVAL;
  354. }
  355. porches = hblk - hslen;
  356. drm_dbg_kms(dev, "Remaining horizontal pixels for both porches: %u\n", porches);
  357. porches_duration_ns = porches * pixel_duration_ns;
  358. if (!bt601 &&
  359. (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) ||
  360. porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) {
  361. drm_err(dev, "Invalid horizontal porches duration: %uns\n",
  362. porches_duration_ns);
  363. return -EINVAL;
  364. }
  365. if (bt601) {
  366. hfp = params->bt601_hfp;
  367. } else {
  368. unsigned int hfp_min = DIV_ROUND_UP(params->hfp_ns.min,
  369. pixel_duration_ns);
  370. unsigned int hbp_min = DIV_ROUND_UP(params->hbp_ns.min,
  371. pixel_duration_ns);
  372. int porches_rem = porches - hfp_min - hbp_min;
  373. hfp = hfp_min + DIV_ROUND_UP(porches_rem, 2);
  374. }
  375. drm_dbg_kms(dev, "Horizontal Front Porch: %u\n", hfp);
  376. hfp_duration_ns = hfp * pixel_duration_ns;
  377. if (!bt601 &&
  378. (hfp_duration_ns < params->hfp_ns.min ||
  379. hfp_duration_ns > params->hfp_ns.max)) {
  380. drm_err(dev, "Invalid horizontal front porch duration: %uns (min: %u, max %u)\n",
  381. hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max);
  382. return -EINVAL;
  383. }
  384. hbp = porches - hfp;
  385. drm_dbg_kms(dev, "Horizontal Back Porch: %u\n", hbp);
  386. hbp_duration_ns = hbp * pixel_duration_ns;
  387. if (!bt601 &&
  388. (hbp_duration_ns < params->hbp_ns.min ||
  389. hbp_duration_ns > params->hbp_ns.max)) {
  390. drm_err(dev, "Invalid horizontal back porch duration: %uns (min: %u, max %u)\n",
  391. hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max);
  392. return -EINVAL;
  393. }
  394. if (htotal != (hactive + hfp + hslen + hbp))
  395. return -EINVAL;
  396. mode->clock = pixel_clock_hz / 1000;
  397. mode->hdisplay = hactive;
  398. mode->hsync_start = mode->hdisplay + hfp;
  399. mode->hsync_end = mode->hsync_start + hslen;
  400. mode->htotal = mode->hsync_end + hbp;
  401. if (interlace) {
  402. vfp_min = params->vfp_lines.even + params->vfp_lines.odd;
  403. vbp_min = params->vbp_lines.even + params->vbp_lines.odd;
  404. vslen = params->vslen_lines.even + params->vslen_lines.odd;
  405. } else {
  406. /*
  407. * By convention, NTSC (aka 525/60) systems start with
  408. * the even field, but PAL (aka 625/50) systems start
  409. * with the odd one.
  410. *
  411. * PAL systems also have asymmetric timings between the
  412. * even and odd field, while NTSC is symmetric.
  413. *
  414. * Moreover, if we want to create a progressive mode for
  415. * PAL, we need to use the odd field timings.
  416. *
  417. * Since odd == even for NTSC, we can just use the odd
  418. * one all the time to simplify the code a bit.
  419. */
  420. vfp_min = params->vfp_lines.odd;
  421. vbp_min = params->vbp_lines.odd;
  422. vslen = params->vslen_lines.odd;
  423. }
  424. drm_dbg_kms(dev, "Vertical Sync Period: %u\n", vslen);
  425. porches = params->num_lines - vactive - vslen;
  426. drm_dbg_kms(dev, "Remaining vertical pixels for both porches: %u\n", porches);
  427. porches_rem = porches - vfp_min - vbp_min;
  428. vfp = vfp_min + (porches_rem / 2);
  429. drm_dbg_kms(dev, "Vertical Front Porch: %u\n", vfp);
  430. vbp = porches - vfp;
  431. drm_dbg_kms(dev, "Vertical Back Porch: %u\n", vbp);
  432. vtotal = vactive + vfp + vslen + vbp;
  433. if (params->num_lines != vtotal) {
  434. drm_err(dev, "Invalid vertical total: %upx (expected %upx)\n",
  435. vtotal, params->num_lines);
  436. return -EINVAL;
  437. }
  438. mode->vdisplay = vactive;
  439. mode->vsync_start = mode->vdisplay + vfp;
  440. mode->vsync_end = mode->vsync_start + vslen;
  441. mode->vtotal = mode->vsync_end + vbp;
  442. if (mode->vtotal != params->num_lines)
  443. return -EINVAL;
  444. mode->type = DRM_MODE_TYPE_DRIVER;
  445. mode->flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC;
  446. if (interlace)
  447. mode->flags |= DRM_MODE_FLAG_INTERLACE;
  448. drm_mode_set_name(mode);
  449. drm_dbg_kms(dev, "Generated mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  450. return 0;
  451. }
  452. /**
  453. * drm_analog_tv_mode - create a display mode for an analog TV
  454. * @dev: drm device
  455. * @tv_mode: TV Mode standard to create a mode for. See DRM_MODE_TV_MODE_*.
  456. * @pixel_clock_hz: Pixel Clock Frequency, in Hertz
  457. * @hdisplay: hdisplay size
  458. * @vdisplay: vdisplay size
  459. * @interlace: whether to compute an interlaced mode
  460. *
  461. * This function creates a struct drm_display_mode instance suited for
  462. * an analog TV output, for one of the usual analog TV modes. Where
  463. * this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created.
  464. *
  465. * Note that @hdisplay is larger than the usual constraints for the PAL
  466. * and NTSC timings, and we'll choose to ignore most timings constraints
  467. * to reach those resolutions.
  468. *
  469. * Returns:
  470. * A pointer to the mode, allocated with drm_mode_create(). Returns NULL
  471. * on error.
  472. */
  473. struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
  474. enum drm_connector_tv_mode tv_mode,
  475. unsigned long pixel_clock_hz,
  476. unsigned int hdisplay,
  477. unsigned int vdisplay,
  478. bool interlace)
  479. {
  480. struct drm_display_mode *mode;
  481. enum drm_mode_analog analog;
  482. int ret;
  483. switch (tv_mode) {
  484. case DRM_MODE_TV_MODE_NTSC:
  485. fallthrough;
  486. case DRM_MODE_TV_MODE_NTSC_443:
  487. fallthrough;
  488. case DRM_MODE_TV_MODE_NTSC_J:
  489. fallthrough;
  490. case DRM_MODE_TV_MODE_PAL_M:
  491. analog = DRM_MODE_ANALOG_NTSC;
  492. break;
  493. case DRM_MODE_TV_MODE_PAL:
  494. fallthrough;
  495. case DRM_MODE_TV_MODE_PAL_N:
  496. fallthrough;
  497. case DRM_MODE_TV_MODE_SECAM:
  498. fallthrough;
  499. case DRM_MODE_TV_MODE_MONOCHROME:
  500. analog = DRM_MODE_ANALOG_PAL;
  501. break;
  502. default:
  503. return NULL;
  504. }
  505. mode = drm_mode_create(dev);
  506. if (!mode)
  507. return NULL;
  508. ret = fill_analog_mode(dev, mode,
  509. &tv_modes_parameters[analog],
  510. pixel_clock_hz, hdisplay, vdisplay, interlace);
  511. if (ret)
  512. goto err_free_mode;
  513. return mode;
  514. err_free_mode:
  515. drm_mode_destroy(dev, mode);
  516. return NULL;
  517. }
  518. EXPORT_SYMBOL(drm_analog_tv_mode);
  519. /**
  520. * drm_cvt_mode -create a modeline based on the CVT algorithm
  521. * @dev: drm device
  522. * @hdisplay: hdisplay size
  523. * @vdisplay: vdisplay size
  524. * @vrefresh: vrefresh rate
  525. * @reduced: whether to use reduced blanking
  526. * @interlaced: whether to compute an interlaced mode
  527. * @margins: whether to add margins (borders)
  528. *
  529. * This function is called to generate the modeline based on CVT algorithm
  530. * according to the hdisplay, vdisplay, vrefresh.
  531. * It is based from the VESA(TM) Coordinated Video Timing Generator by
  532. * Graham Loveridge April 9, 2003 available at
  533. * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
  534. *
  535. * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
  536. * What I have done is to translate it by using integer calculation.
  537. *
  538. * Returns:
  539. * The modeline based on the CVT algorithm stored in a drm_display_mode object.
  540. * The display mode object is allocated with drm_mode_create(). Returns NULL
  541. * when no mode could be allocated.
  542. */
  543. struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
  544. int vdisplay, int vrefresh,
  545. bool reduced, bool interlaced, bool margins)
  546. {
  547. #define HV_FACTOR 1000
  548. /* 1) top/bottom margin size (% of height) - default: 1.8, */
  549. #define CVT_MARGIN_PERCENTAGE 18
  550. /* 2) character cell horizontal granularity (pixels) - default 8 */
  551. #define CVT_H_GRANULARITY 8
  552. /* 3) Minimum vertical porch (lines) - default 3 */
  553. #define CVT_MIN_V_PORCH 3
  554. /* 4) Minimum number of vertical back porch lines - default 6 */
  555. #define CVT_MIN_V_BPORCH 6
  556. /* Pixel Clock step (kHz) */
  557. #define CVT_CLOCK_STEP 250
  558. struct drm_display_mode *drm_mode;
  559. unsigned int vfieldrate, hperiod;
  560. int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
  561. int interlace;
  562. u64 tmp;
  563. if (!hdisplay || !vdisplay)
  564. return NULL;
  565. /* allocate the drm_display_mode structure. If failure, we will
  566. * return directly
  567. */
  568. drm_mode = drm_mode_create(dev);
  569. if (!drm_mode)
  570. return NULL;
  571. /* the CVT default refresh rate is 60Hz */
  572. if (!vrefresh)
  573. vrefresh = 60;
  574. /* the required field fresh rate */
  575. if (interlaced)
  576. vfieldrate = vrefresh * 2;
  577. else
  578. vfieldrate = vrefresh;
  579. /* horizontal pixels */
  580. hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY);
  581. /* determine the left&right borders */
  582. hmargin = 0;
  583. if (margins) {
  584. hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
  585. hmargin -= hmargin % CVT_H_GRANULARITY;
  586. }
  587. /* find the total active pixels */
  588. drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin;
  589. /* find the number of lines per field */
  590. if (interlaced)
  591. vdisplay_rnd = vdisplay / 2;
  592. else
  593. vdisplay_rnd = vdisplay;
  594. /* find the top & bottom borders */
  595. vmargin = 0;
  596. if (margins)
  597. vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
  598. drm_mode->vdisplay = vdisplay + 2 * vmargin;
  599. /* Interlaced */
  600. if (interlaced)
  601. interlace = 1;
  602. else
  603. interlace = 0;
  604. /* Determine VSync Width from aspect ratio */
  605. if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay))
  606. vsync = 4;
  607. else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay))
  608. vsync = 5;
  609. else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay))
  610. vsync = 6;
  611. else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay))
  612. vsync = 7;
  613. else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay))
  614. vsync = 7;
  615. else /* custom */
  616. vsync = 10;
  617. if (!reduced) {
  618. /* simplify the GTF calculation */
  619. /* 4) Minimum time of vertical sync + back porch interval (µs)
  620. * default 550.0
  621. */
  622. int tmp1, tmp2;
  623. #define CVT_MIN_VSYNC_BP 550
  624. /* 3) Nominal HSync width (% of line period) - default 8 */
  625. #define CVT_HSYNC_PERCENTAGE 8
  626. unsigned int hblank_percentage;
  627. int vsyncandback_porch, __maybe_unused vback_porch, hblank;
  628. /* estimated the horizontal period */
  629. tmp1 = HV_FACTOR * 1000000 -
  630. CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate;
  631. tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 +
  632. interlace;
  633. hperiod = tmp1 * 2 / (tmp2 * vfieldrate);
  634. tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1;
  635. /* 9. Find number of lines in sync + backporch */
  636. if (tmp1 < (vsync + CVT_MIN_V_PORCH))
  637. vsyncandback_porch = vsync + CVT_MIN_V_PORCH;
  638. else
  639. vsyncandback_porch = tmp1;
  640. /* 10. Find number of lines in back porch */
  641. vback_porch = vsyncandback_porch - vsync;
  642. drm_mode->vtotal = vdisplay_rnd + 2 * vmargin +
  643. vsyncandback_porch + CVT_MIN_V_PORCH;
  644. /* 5) Definition of Horizontal blanking time limitation */
  645. /* Gradient (%/kHz) - default 600 */
  646. #define CVT_M_FACTOR 600
  647. /* Offset (%) - default 40 */
  648. #define CVT_C_FACTOR 40
  649. /* Blanking time scaling factor - default 128 */
  650. #define CVT_K_FACTOR 128
  651. /* Scaling factor weighting - default 20 */
  652. #define CVT_J_FACTOR 20
  653. #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256)
  654. #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
  655. CVT_J_FACTOR)
  656. /* 12. Find ideal blanking duty cycle from formula */
  657. hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME *
  658. hperiod / 1000;
  659. /* 13. Blanking time */
  660. if (hblank_percentage < 20 * HV_FACTOR)
  661. hblank_percentage = 20 * HV_FACTOR;
  662. hblank = drm_mode->hdisplay * hblank_percentage /
  663. (100 * HV_FACTOR - hblank_percentage);
  664. hblank -= hblank % (2 * CVT_H_GRANULARITY);
  665. /* 14. find the total pixels per line */
  666. drm_mode->htotal = drm_mode->hdisplay + hblank;
  667. drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2;
  668. drm_mode->hsync_start = drm_mode->hsync_end -
  669. (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100;
  670. drm_mode->hsync_start += CVT_H_GRANULARITY -
  671. drm_mode->hsync_start % CVT_H_GRANULARITY;
  672. /* fill the Vsync values */
  673. drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH;
  674. drm_mode->vsync_end = drm_mode->vsync_start + vsync;
  675. } else {
  676. /* Reduced blanking */
  677. /* Minimum vertical blanking interval time (µs)- default 460 */
  678. #define CVT_RB_MIN_VBLANK 460
  679. /* Fixed number of clocks for horizontal sync */
  680. #define CVT_RB_H_SYNC 32
  681. /* Fixed number of clocks for horizontal blanking */
  682. #define CVT_RB_H_BLANK 160
  683. /* Fixed number of lines for vertical front porch - default 3*/
  684. #define CVT_RB_VFPORCH 3
  685. int vbilines;
  686. int tmp1, tmp2;
  687. /* 8. Estimate Horizontal period. */
  688. tmp1 = HV_FACTOR * 1000000 -
  689. CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate;
  690. tmp2 = vdisplay_rnd + 2 * vmargin;
  691. hperiod = tmp1 / (tmp2 * vfieldrate);
  692. /* 9. Find number of lines in vertical blanking */
  693. vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1;
  694. /* 10. Check if vertical blanking is sufficient */
  695. if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH))
  696. vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH;
  697. /* 11. Find total number of lines in vertical field */
  698. drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines;
  699. /* 12. Find total number of pixels in a line */
  700. drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
  701. /* Fill in HSync values */
  702. drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
  703. drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC;
  704. /* Fill in VSync values */
  705. drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH;
  706. drm_mode->vsync_end = drm_mode->vsync_start + vsync;
  707. }
  708. /* 15/13. Find pixel clock frequency (kHz for xf86) */
  709. tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */
  710. tmp *= HV_FACTOR * 1000;
  711. do_div(tmp, hperiod);
  712. tmp -= drm_mode->clock % CVT_CLOCK_STEP;
  713. drm_mode->clock = tmp;
  714. /* 18/16. Find actual vertical frame frequency */
  715. /* ignore - just set the mode flag for interlaced */
  716. if (interlaced) {
  717. drm_mode->vtotal *= 2;
  718. drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
  719. }
  720. /* Fill the mode line name */
  721. drm_mode_set_name(drm_mode);
  722. if (reduced)
  723. drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC |
  724. DRM_MODE_FLAG_NVSYNC);
  725. else
  726. drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
  727. DRM_MODE_FLAG_NHSYNC);
  728. return drm_mode;
  729. }
  730. EXPORT_SYMBOL(drm_cvt_mode);
  731. /**
  732. * drm_gtf_mode_complex - create the modeline based on the full GTF algorithm
  733. * @dev: drm device
  734. * @hdisplay: hdisplay size
  735. * @vdisplay: vdisplay size
  736. * @vrefresh: vrefresh rate.
  737. * @interlaced: whether to compute an interlaced mode
  738. * @margins: desired margin (borders) size
  739. * @GTF_M: extended GTF formula parameters
  740. * @GTF_2C: extended GTF formula parameters
  741. * @GTF_K: extended GTF formula parameters
  742. * @GTF_2J: extended GTF formula parameters
  743. *
  744. * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
  745. * in here multiplied by two. For a C of 40, pass in 80.
  746. *
  747. * Returns:
  748. * The modeline based on the full GTF algorithm stored in a drm_display_mode object.
  749. * The display mode object is allocated with drm_mode_create(). Returns NULL
  750. * when no mode could be allocated.
  751. */
  752. struct drm_display_mode *
  753. drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
  754. int vrefresh, bool interlaced, int margins,
  755. int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
  756. { /* 1) top/bottom margin size (% of height) - default: 1.8, */
  757. #define GTF_MARGIN_PERCENTAGE 18
  758. /* 2) character cell horizontal granularity (pixels) - default 8 */
  759. #define GTF_CELL_GRAN 8
  760. /* 3) Minimum vertical porch (lines) - default 3 */
  761. #define GTF_MIN_V_PORCH 1
  762. /* width of vsync in lines */
  763. #define V_SYNC_RQD 3
  764. /* width of hsync as % of total line */
  765. #define H_SYNC_PERCENT 8
  766. /* min time of vsync + back porch (microsec) */
  767. #define MIN_VSYNC_PLUS_BP 550
  768. /* C' and M' are part of the Blanking Duty Cycle computation */
  769. #define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
  770. #define GTF_M_PRIME (GTF_K * GTF_M / 256)
  771. struct drm_display_mode *drm_mode;
  772. unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
  773. int top_margin, bottom_margin;
  774. int interlace;
  775. unsigned int hfreq_est;
  776. int vsync_plus_bp, __maybe_unused vback_porch;
  777. unsigned int vtotal_lines, __maybe_unused vfieldrate_est;
  778. unsigned int __maybe_unused hperiod;
  779. unsigned int vfield_rate, __maybe_unused vframe_rate;
  780. int left_margin, right_margin;
  781. unsigned int total_active_pixels, ideal_duty_cycle;
  782. unsigned int hblank, total_pixels, pixel_freq;
  783. int hsync, hfront_porch, vodd_front_porch_lines;
  784. unsigned int tmp1, tmp2;
  785. if (!hdisplay || !vdisplay)
  786. return NULL;
  787. drm_mode = drm_mode_create(dev);
  788. if (!drm_mode)
  789. return NULL;
  790. /* 1. In order to give correct results, the number of horizontal
  791. * pixels requested is first processed to ensure that it is divisible
  792. * by the character size, by rounding it to the nearest character
  793. * cell boundary:
  794. */
  795. hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
  796. hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN;
  797. /* 2. If interlace is requested, the number of vertical lines assumed
  798. * by the calculation must be halved, as the computation calculates
  799. * the number of vertical lines per field.
  800. */
  801. if (interlaced)
  802. vdisplay_rnd = vdisplay / 2;
  803. else
  804. vdisplay_rnd = vdisplay;
  805. /* 3. Find the frame rate required: */
  806. if (interlaced)
  807. vfieldrate_rqd = vrefresh * 2;
  808. else
  809. vfieldrate_rqd = vrefresh;
  810. /* 4. Find number of lines in Top margin: */
  811. top_margin = 0;
  812. if (margins)
  813. top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
  814. 1000;
  815. /* 5. Find number of lines in bottom margin: */
  816. bottom_margin = top_margin;
  817. /* 6. If interlace is required, then set variable interlace: */
  818. if (interlaced)
  819. interlace = 1;
  820. else
  821. interlace = 0;
  822. /* 7. Estimate the Horizontal frequency */
  823. {
  824. tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500;
  825. tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) *
  826. 2 + interlace;
  827. hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1;
  828. }
  829. /* 8. Find the number of lines in V sync + back porch */
  830. /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
  831. vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000;
  832. vsync_plus_bp = (vsync_plus_bp + 500) / 1000;
  833. /* 9. Find the number of lines in V back porch alone: */
  834. vback_porch = vsync_plus_bp - V_SYNC_RQD;
  835. /* 10. Find the total number of lines in Vertical field period: */
  836. vtotal_lines = vdisplay_rnd + top_margin + bottom_margin +
  837. vsync_plus_bp + GTF_MIN_V_PORCH;
  838. /* 11. Estimate the Vertical field frequency: */
  839. vfieldrate_est = hfreq_est / vtotal_lines;
  840. /* 12. Find the actual horizontal period: */
  841. hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines);
  842. /* 13. Find the actual Vertical field frequency: */
  843. vfield_rate = hfreq_est / vtotal_lines;
  844. /* 14. Find the Vertical frame frequency: */
  845. if (interlaced)
  846. vframe_rate = vfield_rate / 2;
  847. else
  848. vframe_rate = vfield_rate;
  849. /* 15. Find number of pixels in left margin: */
  850. if (margins)
  851. left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
  852. 1000;
  853. else
  854. left_margin = 0;
  855. /* 16.Find number of pixels in right margin: */
  856. right_margin = left_margin;
  857. /* 17.Find total number of active pixels in image and left and right */
  858. total_active_pixels = hdisplay_rnd + left_margin + right_margin;
  859. /* 18.Find the ideal blanking duty cycle from blanking duty cycle */
  860. ideal_duty_cycle = GTF_C_PRIME * 1000 -
  861. (GTF_M_PRIME * 1000000 / hfreq_est);
  862. /* 19.Find the number of pixels in the blanking time to the nearest
  863. * double character cell: */
  864. hblank = total_active_pixels * ideal_duty_cycle /
  865. (100000 - ideal_duty_cycle);
  866. hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN);
  867. hblank = hblank * 2 * GTF_CELL_GRAN;
  868. /* 20.Find total number of pixels: */
  869. total_pixels = total_active_pixels + hblank;
  870. /* 21.Find pixel clock frequency: */
  871. pixel_freq = total_pixels * hfreq_est / 1000;
  872. /* Stage 1 computations are now complete; I should really pass
  873. * the results to another function and do the Stage 2 computations,
  874. * but I only need a few more values so I'll just append the
  875. * computations here for now */
  876. /* 17. Find the number of pixels in the horizontal sync period: */
  877. hsync = H_SYNC_PERCENT * total_pixels / 100;
  878. hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
  879. hsync = hsync * GTF_CELL_GRAN;
  880. /* 18. Find the number of pixels in horizontal front porch period */
  881. hfront_porch = hblank / 2 - hsync;
  882. /* 36. Find the number of lines in the odd front porch period: */
  883. vodd_front_porch_lines = GTF_MIN_V_PORCH ;
  884. /* finally, pack the results in the mode struct */
  885. drm_mode->hdisplay = hdisplay_rnd;
  886. drm_mode->hsync_start = hdisplay_rnd + hfront_porch;
  887. drm_mode->hsync_end = drm_mode->hsync_start + hsync;
  888. drm_mode->htotal = total_pixels;
  889. drm_mode->vdisplay = vdisplay_rnd;
  890. drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines;
  891. drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD;
  892. drm_mode->vtotal = vtotal_lines;
  893. drm_mode->clock = pixel_freq;
  894. if (interlaced) {
  895. drm_mode->vtotal *= 2;
  896. drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
  897. }
  898. drm_mode_set_name(drm_mode);
  899. if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40)
  900. drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
  901. else
  902. drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC;
  903. return drm_mode;
  904. }
  905. EXPORT_SYMBOL(drm_gtf_mode_complex);
  906. /**
  907. * drm_gtf_mode - create the modeline based on the GTF algorithm
  908. * @dev: drm device
  909. * @hdisplay: hdisplay size
  910. * @vdisplay: vdisplay size
  911. * @vrefresh: vrefresh rate.
  912. * @interlaced: whether to compute an interlaced mode
  913. * @margins: desired margin (borders) size
  914. *
  915. * return the modeline based on GTF algorithm
  916. *
  917. * This function is to create the modeline based on the GTF algorithm.
  918. * Generalized Timing Formula is derived from:
  919. *
  920. * GTF Spreadsheet by Andy Morrish (1/5/97)
  921. * available at https://www.vesa.org
  922. *
  923. * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
  924. * What I have done is to translate it by using integer calculation.
  925. * I also refer to the function of fb_get_mode in the file of
  926. * drivers/video/fbmon.c
  927. *
  928. * Standard GTF parameters::
  929. *
  930. * M = 600
  931. * C = 40
  932. * K = 128
  933. * J = 20
  934. *
  935. * Returns:
  936. * The modeline based on the GTF algorithm stored in a drm_display_mode object.
  937. * The display mode object is allocated with drm_mode_create(). Returns NULL
  938. * when no mode could be allocated.
  939. */
  940. struct drm_display_mode *
  941. drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
  942. bool interlaced, int margins)
  943. {
  944. return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh,
  945. interlaced, margins,
  946. 600, 40 * 2, 128, 20 * 2);
  947. }
  948. EXPORT_SYMBOL(drm_gtf_mode);
  949. #ifdef CONFIG_VIDEOMODE_HELPERS
  950. /**
  951. * drm_display_mode_from_videomode - fill in @dmode using @vm,
  952. * @vm: videomode structure to use as source
  953. * @dmode: drm_display_mode structure to use as destination
  954. *
  955. * Fills out @dmode using the display mode specified in @vm.
  956. */
  957. void drm_display_mode_from_videomode(const struct videomode *vm,
  958. struct drm_display_mode *dmode)
  959. {
  960. dmode->hdisplay = vm->hactive;
  961. dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
  962. dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
  963. dmode->htotal = dmode->hsync_end + vm->hback_porch;
  964. dmode->vdisplay = vm->vactive;
  965. dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
  966. dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
  967. dmode->vtotal = dmode->vsync_end + vm->vback_porch;
  968. dmode->clock = vm->pixelclock / 1000;
  969. dmode->flags = 0;
  970. if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
  971. dmode->flags |= DRM_MODE_FLAG_PHSYNC;
  972. else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
  973. dmode->flags |= DRM_MODE_FLAG_NHSYNC;
  974. if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
  975. dmode->flags |= DRM_MODE_FLAG_PVSYNC;
  976. else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
  977. dmode->flags |= DRM_MODE_FLAG_NVSYNC;
  978. if (vm->flags & DISPLAY_FLAGS_INTERLACED)
  979. dmode->flags |= DRM_MODE_FLAG_INTERLACE;
  980. if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
  981. dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
  982. if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
  983. dmode->flags |= DRM_MODE_FLAG_DBLCLK;
  984. drm_mode_set_name(dmode);
  985. }
  986. EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
  987. /**
  988. * drm_display_mode_to_videomode - fill in @vm using @dmode,
  989. * @dmode: drm_display_mode structure to use as source
  990. * @vm: videomode structure to use as destination
  991. *
  992. * Fills out @vm using the display mode specified in @dmode.
  993. */
  994. void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
  995. struct videomode *vm)
  996. {
  997. vm->hactive = dmode->hdisplay;
  998. vm->hfront_porch = dmode->hsync_start - dmode->hdisplay;
  999. vm->hsync_len = dmode->hsync_end - dmode->hsync_start;
  1000. vm->hback_porch = dmode->htotal - dmode->hsync_end;
  1001. vm->vactive = dmode->vdisplay;
  1002. vm->vfront_porch = dmode->vsync_start - dmode->vdisplay;
  1003. vm->vsync_len = dmode->vsync_end - dmode->vsync_start;
  1004. vm->vback_porch = dmode->vtotal - dmode->vsync_end;
  1005. vm->pixelclock = dmode->clock * 1000;
  1006. vm->flags = 0;
  1007. if (dmode->flags & DRM_MODE_FLAG_PHSYNC)
  1008. vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
  1009. else if (dmode->flags & DRM_MODE_FLAG_NHSYNC)
  1010. vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
  1011. if (dmode->flags & DRM_MODE_FLAG_PVSYNC)
  1012. vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
  1013. else if (dmode->flags & DRM_MODE_FLAG_NVSYNC)
  1014. vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
  1015. if (dmode->flags & DRM_MODE_FLAG_INTERLACE)
  1016. vm->flags |= DISPLAY_FLAGS_INTERLACED;
  1017. if (dmode->flags & DRM_MODE_FLAG_DBLSCAN)
  1018. vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
  1019. if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
  1020. vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
  1021. }
  1022. EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
  1023. /**
  1024. * drm_bus_flags_from_videomode - extract information about pixelclk and
  1025. * DE polarity from videomode and store it in a separate variable
  1026. * @vm: videomode structure to use
  1027. * @bus_flags: information about pixelclk, sync and DE polarity will be stored
  1028. * here
  1029. *
  1030. * Sets DRM_BUS_FLAG_DE_(LOW|HIGH), DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE
  1031. * and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS
  1032. * found in @vm
  1033. */
  1034. void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
  1035. {
  1036. *bus_flags = 0;
  1037. if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
  1038. *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
  1039. if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
  1040. *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
  1041. if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
  1042. *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
  1043. if (vm->flags & DISPLAY_FLAGS_SYNC_NEGEDGE)
  1044. *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
  1045. if (vm->flags & DISPLAY_FLAGS_DE_LOW)
  1046. *bus_flags |= DRM_BUS_FLAG_DE_LOW;
  1047. if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
  1048. *bus_flags |= DRM_BUS_FLAG_DE_HIGH;
  1049. }
  1050. EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode);
  1051. #ifdef CONFIG_OF
  1052. /**
  1053. * of_get_drm_display_mode - get a drm_display_mode from devicetree
  1054. * @np: device_node with the timing specification
  1055. * @dmode: will be set to the return value
  1056. * @bus_flags: information about pixelclk, sync and DE polarity
  1057. * @index: index into the list of display timings in devicetree
  1058. *
  1059. * This function is expensive and should only be used, if only one mode is to be
  1060. * read from DT. To get multiple modes start with of_get_display_timings and
  1061. * work with that instead.
  1062. *
  1063. * Returns:
  1064. * 0 on success, a negative errno code when no of videomode node was found.
  1065. */
  1066. int of_get_drm_display_mode(struct device_node *np,
  1067. struct drm_display_mode *dmode, u32 *bus_flags,
  1068. int index)
  1069. {
  1070. struct videomode vm;
  1071. int ret;
  1072. ret = of_get_videomode(np, &vm, index);
  1073. if (ret)
  1074. return ret;
  1075. drm_display_mode_from_videomode(&vm, dmode);
  1076. if (bus_flags)
  1077. drm_bus_flags_from_videomode(&vm, bus_flags);
  1078. pr_debug("%pOF: got %dx%d display mode: " DRM_MODE_FMT "\n",
  1079. np, vm.hactive, vm.vactive, DRM_MODE_ARG(dmode));
  1080. return 0;
  1081. }
  1082. EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
  1083. /**
  1084. * of_get_drm_panel_display_mode - get a panel-timing drm_display_mode from devicetree
  1085. * @np: device_node with the panel-timing specification
  1086. * @dmode: will be set to the return value
  1087. * @bus_flags: information about pixelclk, sync and DE polarity
  1088. *
  1089. * The mandatory Device Tree properties width-mm and height-mm
  1090. * are read and set on the display mode.
  1091. *
  1092. * Returns:
  1093. * Zero on success, negative error code on failure.
  1094. */
  1095. int of_get_drm_panel_display_mode(struct device_node *np,
  1096. struct drm_display_mode *dmode, u32 *bus_flags)
  1097. {
  1098. u32 width_mm = 0, height_mm = 0;
  1099. struct display_timing timing;
  1100. struct videomode vm;
  1101. int ret;
  1102. ret = of_get_display_timing(np, "panel-timing", &timing);
  1103. if (ret)
  1104. return ret;
  1105. videomode_from_timing(&timing, &vm);
  1106. memset(dmode, 0, sizeof(*dmode));
  1107. drm_display_mode_from_videomode(&vm, dmode);
  1108. if (bus_flags)
  1109. drm_bus_flags_from_videomode(&vm, bus_flags);
  1110. ret = of_property_read_u32(np, "width-mm", &width_mm);
  1111. if (ret)
  1112. return ret;
  1113. ret = of_property_read_u32(np, "height-mm", &height_mm);
  1114. if (ret)
  1115. return ret;
  1116. dmode->width_mm = width_mm;
  1117. dmode->height_mm = height_mm;
  1118. pr_debug(DRM_MODE_FMT "\n", DRM_MODE_ARG(dmode));
  1119. return 0;
  1120. }
  1121. EXPORT_SYMBOL_GPL(of_get_drm_panel_display_mode);
  1122. #endif /* CONFIG_OF */
  1123. #endif /* CONFIG_VIDEOMODE_HELPERS */
  1124. /**
  1125. * drm_mode_set_name - set the name on a mode
  1126. * @mode: name will be set in this mode
  1127. *
  1128. * Set the name of @mode to a standard format which is <hdisplay>x<vdisplay>
  1129. * with an optional 'i' suffix for interlaced modes.
  1130. */
  1131. void drm_mode_set_name(struct drm_display_mode *mode)
  1132. {
  1133. bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
  1134. snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
  1135. mode->hdisplay, mode->vdisplay,
  1136. interlaced ? "i" : "");
  1137. }
  1138. EXPORT_SYMBOL(drm_mode_set_name);
  1139. /**
  1140. * drm_mode_vrefresh - get the vrefresh of a mode
  1141. * @mode: mode
  1142. *
  1143. * Returns:
  1144. * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
  1145. * value first if it is not yet set.
  1146. */
  1147. int drm_mode_vrefresh(const struct drm_display_mode *mode)
  1148. {
  1149. unsigned int num = 1, den = 1;
  1150. if (mode->htotal == 0 || mode->vtotal == 0)
  1151. return 0;
  1152. if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  1153. num *= 2;
  1154. if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
  1155. den *= 2;
  1156. if (mode->vscan > 1)
  1157. den *= mode->vscan;
  1158. if (check_mul_overflow(mode->clock, num, &num))
  1159. return 0;
  1160. if (check_mul_overflow(mode->htotal * mode->vtotal, den, &den))
  1161. return 0;
  1162. return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
  1163. }
  1164. EXPORT_SYMBOL(drm_mode_vrefresh);
  1165. /**
  1166. * drm_mode_get_hv_timing - Fetches hdisplay/vdisplay for given mode
  1167. * @mode: mode to query
  1168. * @hdisplay: hdisplay value to fill in
  1169. * @vdisplay: vdisplay value to fill in
  1170. *
  1171. * The vdisplay value will be doubled if the specified mode is a stereo mode of
  1172. * the appropriate layout.
  1173. */
  1174. void drm_mode_get_hv_timing(const struct drm_display_mode *mode,
  1175. int *hdisplay, int *vdisplay)
  1176. {
  1177. struct drm_display_mode adjusted;
  1178. drm_mode_init(&adjusted, mode);
  1179. drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
  1180. *hdisplay = adjusted.crtc_hdisplay;
  1181. *vdisplay = adjusted.crtc_vdisplay;
  1182. }
  1183. EXPORT_SYMBOL(drm_mode_get_hv_timing);
  1184. /**
  1185. * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
  1186. * @p: mode
  1187. * @adjust_flags: a combination of adjustment flags
  1188. *
  1189. * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
  1190. *
  1191. * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
  1192. * interlaced modes.
  1193. * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
  1194. * buffers containing two eyes (only adjust the timings when needed, eg. for
  1195. * "frame packing" or "side by side full").
  1196. * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
  1197. * be performed for doublescan and vscan > 1 modes respectively.
  1198. */
  1199. void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
  1200. {
  1201. if (!p)
  1202. return;
  1203. p->crtc_clock = p->clock;
  1204. p->crtc_hdisplay = p->hdisplay;
  1205. p->crtc_hsync_start = p->hsync_start;
  1206. p->crtc_hsync_end = p->hsync_end;
  1207. p->crtc_htotal = p->htotal;
  1208. p->crtc_hskew = p->hskew;
  1209. p->crtc_vdisplay = p->vdisplay;
  1210. p->crtc_vsync_start = p->vsync_start;
  1211. p->crtc_vsync_end = p->vsync_end;
  1212. p->crtc_vtotal = p->vtotal;
  1213. if (p->flags & DRM_MODE_FLAG_INTERLACE) {
  1214. if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
  1215. p->crtc_vdisplay /= 2;
  1216. p->crtc_vsync_start /= 2;
  1217. p->crtc_vsync_end /= 2;
  1218. p->crtc_vtotal /= 2;
  1219. }
  1220. }
  1221. if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
  1222. if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
  1223. p->crtc_vdisplay *= 2;
  1224. p->crtc_vsync_start *= 2;
  1225. p->crtc_vsync_end *= 2;
  1226. p->crtc_vtotal *= 2;
  1227. }
  1228. }
  1229. if (!(adjust_flags & CRTC_NO_VSCAN)) {
  1230. if (p->vscan > 1) {
  1231. p->crtc_vdisplay *= p->vscan;
  1232. p->crtc_vsync_start *= p->vscan;
  1233. p->crtc_vsync_end *= p->vscan;
  1234. p->crtc_vtotal *= p->vscan;
  1235. }
  1236. }
  1237. if (adjust_flags & CRTC_STEREO_DOUBLE) {
  1238. unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
  1239. switch (layout) {
  1240. case DRM_MODE_FLAG_3D_FRAME_PACKING:
  1241. p->crtc_clock *= 2;
  1242. p->crtc_vdisplay += p->crtc_vtotal;
  1243. p->crtc_vsync_start += p->crtc_vtotal;
  1244. p->crtc_vsync_end += p->crtc_vtotal;
  1245. p->crtc_vtotal += p->crtc_vtotal;
  1246. break;
  1247. }
  1248. }
  1249. p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
  1250. p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
  1251. p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
  1252. p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
  1253. }
  1254. EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  1255. /**
  1256. * drm_mode_copy - copy the mode
  1257. * @dst: mode to overwrite
  1258. * @src: mode to copy
  1259. *
  1260. * Copy an existing mode into another mode, preserving the
  1261. * list head of the destination mode.
  1262. */
  1263. void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
  1264. {
  1265. struct list_head head = dst->head;
  1266. *dst = *src;
  1267. dst->head = head;
  1268. }
  1269. EXPORT_SYMBOL(drm_mode_copy);
  1270. /**
  1271. * drm_mode_init - initialize the mode from another mode
  1272. * @dst: mode to overwrite
  1273. * @src: mode to copy
  1274. *
  1275. * Copy an existing mode into another mode, zeroing the
  1276. * list head of the destination mode. Typically used
  1277. * to guarantee the list head is not left with stack
  1278. * garbage in on-stack modes.
  1279. */
  1280. void drm_mode_init(struct drm_display_mode *dst, const struct drm_display_mode *src)
  1281. {
  1282. memset(dst, 0, sizeof(*dst));
  1283. drm_mode_copy(dst, src);
  1284. }
  1285. EXPORT_SYMBOL(drm_mode_init);
  1286. /**
  1287. * drm_mode_duplicate - allocate and duplicate an existing mode
  1288. * @dev: drm_device to allocate the duplicated mode for
  1289. * @mode: mode to duplicate
  1290. *
  1291. * Just allocate a new mode, copy the existing mode into it, and return
  1292. * a pointer to it. Used to create new instances of established modes.
  1293. *
  1294. * Returns:
  1295. * Pointer to duplicated mode on success, NULL on error.
  1296. */
  1297. struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
  1298. const struct drm_display_mode *mode)
  1299. {
  1300. struct drm_display_mode *nmode;
  1301. nmode = drm_mode_create(dev);
  1302. if (!nmode)
  1303. return NULL;
  1304. drm_mode_copy(nmode, mode);
  1305. return nmode;
  1306. }
  1307. EXPORT_SYMBOL(drm_mode_duplicate);
  1308. static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
  1309. const struct drm_display_mode *mode2)
  1310. {
  1311. return mode1->hdisplay == mode2->hdisplay &&
  1312. mode1->hsync_start == mode2->hsync_start &&
  1313. mode1->hsync_end == mode2->hsync_end &&
  1314. mode1->htotal == mode2->htotal &&
  1315. mode1->hskew == mode2->hskew &&
  1316. mode1->vdisplay == mode2->vdisplay &&
  1317. mode1->vsync_start == mode2->vsync_start &&
  1318. mode1->vsync_end == mode2->vsync_end &&
  1319. mode1->vtotal == mode2->vtotal &&
  1320. mode1->vscan == mode2->vscan;
  1321. }
  1322. static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
  1323. const struct drm_display_mode *mode2)
  1324. {
  1325. /*
  1326. * do clock check convert to PICOS
  1327. * so fb modes get matched the same
  1328. */
  1329. if (mode1->clock && mode2->clock)
  1330. return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
  1331. else
  1332. return mode1->clock == mode2->clock;
  1333. }
  1334. static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
  1335. const struct drm_display_mode *mode2)
  1336. {
  1337. return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
  1338. (mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
  1339. }
  1340. static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
  1341. const struct drm_display_mode *mode2)
  1342. {
  1343. return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
  1344. (mode2->flags & DRM_MODE_FLAG_3D_MASK);
  1345. }
  1346. static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
  1347. const struct drm_display_mode *mode2)
  1348. {
  1349. return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
  1350. }
  1351. /**
  1352. * drm_mode_match - test modes for (partial) equality
  1353. * @mode1: first mode
  1354. * @mode2: second mode
  1355. * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
  1356. *
  1357. * Check to see if @mode1 and @mode2 are equivalent.
  1358. *
  1359. * Returns:
  1360. * True if the modes are (partially) equal, false otherwise.
  1361. */
  1362. bool drm_mode_match(const struct drm_display_mode *mode1,
  1363. const struct drm_display_mode *mode2,
  1364. unsigned int match_flags)
  1365. {
  1366. if (!mode1 && !mode2)
  1367. return true;
  1368. if (!mode1 || !mode2)
  1369. return false;
  1370. if (match_flags & DRM_MODE_MATCH_TIMINGS &&
  1371. !drm_mode_match_timings(mode1, mode2))
  1372. return false;
  1373. if (match_flags & DRM_MODE_MATCH_CLOCK &&
  1374. !drm_mode_match_clock(mode1, mode2))
  1375. return false;
  1376. if (match_flags & DRM_MODE_MATCH_FLAGS &&
  1377. !drm_mode_match_flags(mode1, mode2))
  1378. return false;
  1379. if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
  1380. !drm_mode_match_3d_flags(mode1, mode2))
  1381. return false;
  1382. if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
  1383. !drm_mode_match_aspect_ratio(mode1, mode2))
  1384. return false;
  1385. return true;
  1386. }
  1387. EXPORT_SYMBOL(drm_mode_match);
  1388. /**
  1389. * drm_mode_equal - test modes for equality
  1390. * @mode1: first mode
  1391. * @mode2: second mode
  1392. *
  1393. * Check to see if @mode1 and @mode2 are equivalent.
  1394. *
  1395. * Returns:
  1396. * True if the modes are equal, false otherwise.
  1397. */
  1398. bool drm_mode_equal(const struct drm_display_mode *mode1,
  1399. const struct drm_display_mode *mode2)
  1400. {
  1401. return drm_mode_match(mode1, mode2,
  1402. DRM_MODE_MATCH_TIMINGS |
  1403. DRM_MODE_MATCH_CLOCK |
  1404. DRM_MODE_MATCH_FLAGS |
  1405. DRM_MODE_MATCH_3D_FLAGS|
  1406. DRM_MODE_MATCH_ASPECT_RATIO);
  1407. }
  1408. EXPORT_SYMBOL(drm_mode_equal);
  1409. /**
  1410. * drm_mode_equal_no_clocks - test modes for equality
  1411. * @mode1: first mode
  1412. * @mode2: second mode
  1413. *
  1414. * Check to see if @mode1 and @mode2 are equivalent, but
  1415. * don't check the pixel clocks.
  1416. *
  1417. * Returns:
  1418. * True if the modes are equal, false otherwise.
  1419. */
  1420. bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
  1421. const struct drm_display_mode *mode2)
  1422. {
  1423. return drm_mode_match(mode1, mode2,
  1424. DRM_MODE_MATCH_TIMINGS |
  1425. DRM_MODE_MATCH_FLAGS |
  1426. DRM_MODE_MATCH_3D_FLAGS);
  1427. }
  1428. EXPORT_SYMBOL(drm_mode_equal_no_clocks);
  1429. /**
  1430. * drm_mode_equal_no_clocks_no_stereo - test modes for equality
  1431. * @mode1: first mode
  1432. * @mode2: second mode
  1433. *
  1434. * Check to see if @mode1 and @mode2 are equivalent, but
  1435. * don't check the pixel clocks nor the stereo layout.
  1436. *
  1437. * Returns:
  1438. * True if the modes are equal, false otherwise.
  1439. */
  1440. bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
  1441. const struct drm_display_mode *mode2)
  1442. {
  1443. return drm_mode_match(mode1, mode2,
  1444. DRM_MODE_MATCH_TIMINGS |
  1445. DRM_MODE_MATCH_FLAGS);
  1446. }
  1447. EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
  1448. static enum drm_mode_status
  1449. drm_mode_validate_basic(const struct drm_display_mode *mode)
  1450. {
  1451. if (mode->type & ~DRM_MODE_TYPE_ALL)
  1452. return MODE_BAD;
  1453. if (mode->flags & ~DRM_MODE_FLAG_ALL)
  1454. return MODE_BAD;
  1455. if ((mode->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
  1456. return MODE_BAD;
  1457. if (mode->clock == 0)
  1458. return MODE_CLOCK_LOW;
  1459. if (mode->hdisplay == 0 ||
  1460. mode->hsync_start < mode->hdisplay ||
  1461. mode->hsync_end < mode->hsync_start ||
  1462. mode->htotal < mode->hsync_end)
  1463. return MODE_H_ILLEGAL;
  1464. if (mode->vdisplay == 0 ||
  1465. mode->vsync_start < mode->vdisplay ||
  1466. mode->vsync_end < mode->vsync_start ||
  1467. mode->vtotal < mode->vsync_end)
  1468. return MODE_V_ILLEGAL;
  1469. return MODE_OK;
  1470. }
  1471. /**
  1472. * drm_mode_validate_driver - make sure the mode is somewhat sane
  1473. * @dev: drm device
  1474. * @mode: mode to check
  1475. *
  1476. * First do basic validation on the mode, and then allow the driver
  1477. * to check for device/driver specific limitations via the optional
  1478. * &drm_mode_config_helper_funcs.mode_valid hook.
  1479. *
  1480. * Returns:
  1481. * The mode status
  1482. */
  1483. enum drm_mode_status
  1484. drm_mode_validate_driver(struct drm_device *dev,
  1485. const struct drm_display_mode *mode)
  1486. {
  1487. enum drm_mode_status status;
  1488. status = drm_mode_validate_basic(mode);
  1489. if (status != MODE_OK)
  1490. return status;
  1491. if (dev->mode_config.funcs->mode_valid)
  1492. return dev->mode_config.funcs->mode_valid(dev, mode);
  1493. else
  1494. return MODE_OK;
  1495. }
  1496. EXPORT_SYMBOL(drm_mode_validate_driver);
  1497. /**
  1498. * drm_mode_validate_size - make sure modes adhere to size constraints
  1499. * @mode: mode to check
  1500. * @maxX: maximum width
  1501. * @maxY: maximum height
  1502. *
  1503. * This function is a helper which can be used to validate modes against size
  1504. * limitations of the DRM device/connector. If a mode is too big its status
  1505. * member is updated with the appropriate validation failure code. The list
  1506. * itself is not changed.
  1507. *
  1508. * Returns:
  1509. * The mode status
  1510. */
  1511. enum drm_mode_status
  1512. drm_mode_validate_size(const struct drm_display_mode *mode,
  1513. int maxX, int maxY)
  1514. {
  1515. if (maxX > 0 && mode->hdisplay > maxX)
  1516. return MODE_VIRTUAL_X;
  1517. if (maxY > 0 && mode->vdisplay > maxY)
  1518. return MODE_VIRTUAL_Y;
  1519. return MODE_OK;
  1520. }
  1521. EXPORT_SYMBOL(drm_mode_validate_size);
  1522. /**
  1523. * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
  1524. * @mode: mode to check
  1525. * @connector: drm connector under action
  1526. *
  1527. * This function is a helper which can be used to filter out any YCBCR420
  1528. * only mode, when the source doesn't support it.
  1529. *
  1530. * Returns:
  1531. * The mode status
  1532. */
  1533. enum drm_mode_status
  1534. drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
  1535. struct drm_connector *connector)
  1536. {
  1537. if (!connector->ycbcr_420_allowed &&
  1538. drm_mode_is_420_only(&connector->display_info, mode))
  1539. return MODE_NO_420;
  1540. return MODE_OK;
  1541. }
  1542. EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
  1543. #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
  1544. static const char * const drm_mode_status_names[] = {
  1545. MODE_STATUS(OK),
  1546. MODE_STATUS(HSYNC),
  1547. MODE_STATUS(VSYNC),
  1548. MODE_STATUS(H_ILLEGAL),
  1549. MODE_STATUS(V_ILLEGAL),
  1550. MODE_STATUS(BAD_WIDTH),
  1551. MODE_STATUS(NOMODE),
  1552. MODE_STATUS(NO_INTERLACE),
  1553. MODE_STATUS(NO_DBLESCAN),
  1554. MODE_STATUS(NO_VSCAN),
  1555. MODE_STATUS(MEM),
  1556. MODE_STATUS(VIRTUAL_X),
  1557. MODE_STATUS(VIRTUAL_Y),
  1558. MODE_STATUS(MEM_VIRT),
  1559. MODE_STATUS(NOCLOCK),
  1560. MODE_STATUS(CLOCK_HIGH),
  1561. MODE_STATUS(CLOCK_LOW),
  1562. MODE_STATUS(CLOCK_RANGE),
  1563. MODE_STATUS(BAD_HVALUE),
  1564. MODE_STATUS(BAD_VVALUE),
  1565. MODE_STATUS(BAD_VSCAN),
  1566. MODE_STATUS(HSYNC_NARROW),
  1567. MODE_STATUS(HSYNC_WIDE),
  1568. MODE_STATUS(HBLANK_NARROW),
  1569. MODE_STATUS(HBLANK_WIDE),
  1570. MODE_STATUS(VSYNC_NARROW),
  1571. MODE_STATUS(VSYNC_WIDE),
  1572. MODE_STATUS(VBLANK_NARROW),
  1573. MODE_STATUS(VBLANK_WIDE),
  1574. MODE_STATUS(PANEL),
  1575. MODE_STATUS(INTERLACE_WIDTH),
  1576. MODE_STATUS(ONE_WIDTH),
  1577. MODE_STATUS(ONE_HEIGHT),
  1578. MODE_STATUS(ONE_SIZE),
  1579. MODE_STATUS(NO_REDUCED),
  1580. MODE_STATUS(NO_STEREO),
  1581. MODE_STATUS(NO_420),
  1582. MODE_STATUS(STALE),
  1583. MODE_STATUS(BAD),
  1584. MODE_STATUS(ERROR),
  1585. };
  1586. #undef MODE_STATUS
  1587. const char *drm_get_mode_status_name(enum drm_mode_status status)
  1588. {
  1589. int index = status + 3;
  1590. if (WARN_ON(index < 0 || index >= ARRAY_SIZE(drm_mode_status_names)))
  1591. return "";
  1592. return drm_mode_status_names[index];
  1593. }
  1594. /**
  1595. * drm_mode_prune_invalid - remove invalid modes from mode list
  1596. * @dev: DRM device
  1597. * @mode_list: list of modes to check
  1598. * @verbose: be verbose about it
  1599. *
  1600. * This helper function can be used to prune a display mode list after
  1601. * validation has been completed. All modes whose status is not MODE_OK will be
  1602. * removed from the list, and if @verbose the status code and mode name is also
  1603. * printed to dmesg.
  1604. */
  1605. void drm_mode_prune_invalid(struct drm_device *dev,
  1606. struct list_head *mode_list, bool verbose)
  1607. {
  1608. struct drm_display_mode *mode, *t;
  1609. list_for_each_entry_safe(mode, t, mode_list, head) {
  1610. if (mode->status != MODE_OK) {
  1611. list_del(&mode->head);
  1612. if (mode->type & DRM_MODE_TYPE_USERDEF) {
  1613. drm_warn(dev, "User-defined mode not supported: "
  1614. DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  1615. }
  1616. if (verbose) {
  1617. drm_dbg_kms(dev, "Rejected mode: " DRM_MODE_FMT " (%s)\n",
  1618. DRM_MODE_ARG(mode), drm_get_mode_status_name(mode->status));
  1619. }
  1620. drm_mode_destroy(dev, mode);
  1621. }
  1622. }
  1623. }
  1624. EXPORT_SYMBOL(drm_mode_prune_invalid);
  1625. /**
  1626. * drm_mode_compare - compare modes for favorability
  1627. * @priv: unused
  1628. * @lh_a: list_head for first mode
  1629. * @lh_b: list_head for second mode
  1630. *
  1631. * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
  1632. * which is better.
  1633. *
  1634. * Returns:
  1635. * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
  1636. * positive if @lh_b is better than @lh_a.
  1637. */
  1638. static int drm_mode_compare(void *priv, const struct list_head *lh_a,
  1639. const struct list_head *lh_b)
  1640. {
  1641. struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
  1642. struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
  1643. int diff;
  1644. diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
  1645. ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
  1646. if (diff)
  1647. return diff;
  1648. diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
  1649. if (diff)
  1650. return diff;
  1651. diff = drm_mode_vrefresh(b) - drm_mode_vrefresh(a);
  1652. if (diff)
  1653. return diff;
  1654. diff = b->clock - a->clock;
  1655. return diff;
  1656. }
  1657. /**
  1658. * drm_mode_sort - sort mode list
  1659. * @mode_list: list of drm_display_mode structures to sort
  1660. *
  1661. * Sort @mode_list by favorability, moving good modes to the head of the list.
  1662. */
  1663. void drm_mode_sort(struct list_head *mode_list)
  1664. {
  1665. list_sort(NULL, mode_list, drm_mode_compare);
  1666. }
  1667. EXPORT_SYMBOL(drm_mode_sort);
  1668. /**
  1669. * drm_connector_list_update - update the mode list for the connector
  1670. * @connector: the connector to update
  1671. *
  1672. * This moves the modes from the @connector probed_modes list
  1673. * to the actual mode list. It compares the probed mode against the current
  1674. * list and only adds different/new modes.
  1675. *
  1676. * This is just a helper functions doesn't validate any modes itself and also
  1677. * doesn't prune any invalid modes. Callers need to do that themselves.
  1678. */
  1679. void drm_connector_list_update(struct drm_connector *connector)
  1680. {
  1681. struct drm_display_mode *pmode, *pt;
  1682. WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
  1683. list_for_each_entry_safe(pmode, pt, &connector->probed_modes, head) {
  1684. struct drm_display_mode *mode;
  1685. bool found_it = false;
  1686. /* go through current modes checking for the new probed mode */
  1687. list_for_each_entry(mode, &connector->modes, head) {
  1688. if (!drm_mode_equal(pmode, mode))
  1689. continue;
  1690. found_it = true;
  1691. /*
  1692. * If the old matching mode is stale (ie. left over
  1693. * from a previous probe) just replace it outright.
  1694. * Otherwise just merge the type bits between all
  1695. * equal probed modes.
  1696. *
  1697. * If two probed modes are considered equal, pick the
  1698. * actual timings from the one that's marked as
  1699. * preferred (in case the match isn't 100%). If
  1700. * multiple or zero preferred modes are present, favor
  1701. * the mode added to the probed_modes list first.
  1702. */
  1703. if (mode->status == MODE_STALE) {
  1704. drm_mode_copy(mode, pmode);
  1705. } else if ((mode->type & DRM_MODE_TYPE_PREFERRED) == 0 &&
  1706. (pmode->type & DRM_MODE_TYPE_PREFERRED) != 0) {
  1707. pmode->type |= mode->type;
  1708. drm_mode_copy(mode, pmode);
  1709. } else {
  1710. mode->type |= pmode->type;
  1711. }
  1712. list_del(&pmode->head);
  1713. drm_mode_destroy(connector->dev, pmode);
  1714. break;
  1715. }
  1716. if (!found_it) {
  1717. list_move_tail(&pmode->head, &connector->modes);
  1718. }
  1719. }
  1720. }
  1721. EXPORT_SYMBOL(drm_connector_list_update);
  1722. static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
  1723. struct drm_cmdline_mode *mode)
  1724. {
  1725. unsigned int bpp;
  1726. if (str[0] != '-')
  1727. return -EINVAL;
  1728. str++;
  1729. bpp = simple_strtol(str, end_ptr, 10);
  1730. if (*end_ptr == str)
  1731. return -EINVAL;
  1732. mode->bpp = bpp;
  1733. mode->bpp_specified = true;
  1734. return 0;
  1735. }
  1736. static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
  1737. struct drm_cmdline_mode *mode)
  1738. {
  1739. unsigned int refresh;
  1740. if (str[0] != '@')
  1741. return -EINVAL;
  1742. str++;
  1743. refresh = simple_strtol(str, end_ptr, 10);
  1744. if (*end_ptr == str)
  1745. return -EINVAL;
  1746. mode->refresh = refresh;
  1747. mode->refresh_specified = true;
  1748. return 0;
  1749. }
  1750. static int drm_mode_parse_cmdline_extra(const char *str, int length,
  1751. bool freestanding,
  1752. const struct drm_connector *connector,
  1753. struct drm_cmdline_mode *mode)
  1754. {
  1755. int i;
  1756. for (i = 0; i < length; i++) {
  1757. switch (str[i]) {
  1758. case 'i':
  1759. if (freestanding)
  1760. return -EINVAL;
  1761. mode->interlace = true;
  1762. break;
  1763. case 'm':
  1764. if (freestanding)
  1765. return -EINVAL;
  1766. mode->margins = true;
  1767. break;
  1768. case 'D':
  1769. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1770. return -EINVAL;
  1771. if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
  1772. (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
  1773. mode->force = DRM_FORCE_ON;
  1774. else
  1775. mode->force = DRM_FORCE_ON_DIGITAL;
  1776. break;
  1777. case 'd':
  1778. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1779. return -EINVAL;
  1780. mode->force = DRM_FORCE_OFF;
  1781. break;
  1782. case 'e':
  1783. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1784. return -EINVAL;
  1785. mode->force = DRM_FORCE_ON;
  1786. break;
  1787. default:
  1788. return -EINVAL;
  1789. }
  1790. }
  1791. return 0;
  1792. }
  1793. static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
  1794. bool extras,
  1795. const struct drm_connector *connector,
  1796. struct drm_cmdline_mode *mode)
  1797. {
  1798. const char *str_start = str;
  1799. bool rb = false, cvt = false;
  1800. int xres = 0, yres = 0;
  1801. int remaining, i;
  1802. char *end_ptr;
  1803. xres = simple_strtol(str, &end_ptr, 10);
  1804. if (end_ptr == str)
  1805. return -EINVAL;
  1806. if (end_ptr[0] != 'x')
  1807. return -EINVAL;
  1808. end_ptr++;
  1809. str = end_ptr;
  1810. yres = simple_strtol(str, &end_ptr, 10);
  1811. if (end_ptr == str)
  1812. return -EINVAL;
  1813. remaining = length - (end_ptr - str_start);
  1814. if (remaining < 0)
  1815. return -EINVAL;
  1816. for (i = 0; i < remaining; i++) {
  1817. switch (end_ptr[i]) {
  1818. case 'M':
  1819. cvt = true;
  1820. break;
  1821. case 'R':
  1822. rb = true;
  1823. break;
  1824. default:
  1825. /*
  1826. * Try to pass that to our extras parsing
  1827. * function to handle the case where the
  1828. * extras are directly after the resolution
  1829. */
  1830. if (extras) {
  1831. int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
  1832. 1,
  1833. false,
  1834. connector,
  1835. mode);
  1836. if (ret)
  1837. return ret;
  1838. } else {
  1839. return -EINVAL;
  1840. }
  1841. }
  1842. }
  1843. mode->xres = xres;
  1844. mode->yres = yres;
  1845. mode->cvt = cvt;
  1846. mode->rb = rb;
  1847. return 0;
  1848. }
  1849. static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
  1850. {
  1851. const char *value;
  1852. char *endp;
  1853. /*
  1854. * delim must point to the '=', otherwise it is a syntax error and
  1855. * if delim points to the terminating zero, then delim + 1 will point
  1856. * past the end of the string.
  1857. */
  1858. if (*delim != '=')
  1859. return -EINVAL;
  1860. value = delim + 1;
  1861. *int_ret = simple_strtol(value, &endp, 10);
  1862. /* Make sure we have parsed something */
  1863. if (endp == value)
  1864. return -EINVAL;
  1865. return 0;
  1866. }
  1867. static int drm_mode_parse_panel_orientation(const char *delim,
  1868. struct drm_cmdline_mode *mode)
  1869. {
  1870. const char *value;
  1871. if (*delim != '=')
  1872. return -EINVAL;
  1873. value = delim + 1;
  1874. delim = strchr(value, ',');
  1875. if (!delim)
  1876. delim = value + strlen(value);
  1877. if (!strncmp(value, "normal", delim - value))
  1878. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
  1879. else if (!strncmp(value, "upside_down", delim - value))
  1880. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
  1881. else if (!strncmp(value, "left_side_up", delim - value))
  1882. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
  1883. else if (!strncmp(value, "right_side_up", delim - value))
  1884. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
  1885. else
  1886. return -EINVAL;
  1887. return 0;
  1888. }
  1889. static int drm_mode_parse_tv_mode(const char *delim,
  1890. struct drm_cmdline_mode *mode)
  1891. {
  1892. const char *value;
  1893. int ret;
  1894. if (*delim != '=')
  1895. return -EINVAL;
  1896. value = delim + 1;
  1897. delim = strchr(value, ',');
  1898. if (!delim)
  1899. delim = value + strlen(value);
  1900. ret = drm_get_tv_mode_from_name(value, delim - value);
  1901. if (ret < 0)
  1902. return ret;
  1903. mode->tv_mode_specified = true;
  1904. mode->tv_mode = ret;
  1905. return 0;
  1906. }
  1907. static int drm_mode_parse_cmdline_options(const char *str,
  1908. bool freestanding,
  1909. const struct drm_connector *connector,
  1910. struct drm_cmdline_mode *mode)
  1911. {
  1912. unsigned int deg, margin, rotation = 0;
  1913. const char *delim, *option, *sep;
  1914. option = str;
  1915. do {
  1916. delim = strchr(option, '=');
  1917. if (!delim) {
  1918. delim = strchr(option, ',');
  1919. if (!delim)
  1920. delim = option + strlen(option);
  1921. }
  1922. if (!strncmp(option, "rotate", delim - option)) {
  1923. if (drm_mode_parse_cmdline_int(delim, &deg))
  1924. return -EINVAL;
  1925. switch (deg) {
  1926. case 0:
  1927. rotation |= DRM_MODE_ROTATE_0;
  1928. break;
  1929. case 90:
  1930. rotation |= DRM_MODE_ROTATE_90;
  1931. break;
  1932. case 180:
  1933. rotation |= DRM_MODE_ROTATE_180;
  1934. break;
  1935. case 270:
  1936. rotation |= DRM_MODE_ROTATE_270;
  1937. break;
  1938. default:
  1939. return -EINVAL;
  1940. }
  1941. } else if (!strncmp(option, "reflect_x", delim - option)) {
  1942. rotation |= DRM_MODE_REFLECT_X;
  1943. } else if (!strncmp(option, "reflect_y", delim - option)) {
  1944. rotation |= DRM_MODE_REFLECT_Y;
  1945. } else if (!strncmp(option, "margin_right", delim - option)) {
  1946. if (drm_mode_parse_cmdline_int(delim, &margin))
  1947. return -EINVAL;
  1948. mode->tv_margins.right = margin;
  1949. } else if (!strncmp(option, "margin_left", delim - option)) {
  1950. if (drm_mode_parse_cmdline_int(delim, &margin))
  1951. return -EINVAL;
  1952. mode->tv_margins.left = margin;
  1953. } else if (!strncmp(option, "margin_top", delim - option)) {
  1954. if (drm_mode_parse_cmdline_int(delim, &margin))
  1955. return -EINVAL;
  1956. mode->tv_margins.top = margin;
  1957. } else if (!strncmp(option, "margin_bottom", delim - option)) {
  1958. if (drm_mode_parse_cmdline_int(delim, &margin))
  1959. return -EINVAL;
  1960. mode->tv_margins.bottom = margin;
  1961. } else if (!strncmp(option, "panel_orientation", delim - option)) {
  1962. if (drm_mode_parse_panel_orientation(delim, mode))
  1963. return -EINVAL;
  1964. } else if (!strncmp(option, "tv_mode", delim - option)) {
  1965. if (drm_mode_parse_tv_mode(delim, mode))
  1966. return -EINVAL;
  1967. } else {
  1968. return -EINVAL;
  1969. }
  1970. sep = strchr(delim, ',');
  1971. option = sep + 1;
  1972. } while (sep);
  1973. if (rotation && freestanding)
  1974. return -EINVAL;
  1975. if (!(rotation & DRM_MODE_ROTATE_MASK))
  1976. rotation |= DRM_MODE_ROTATE_0;
  1977. /* Make sure there is exactly one rotation defined */
  1978. if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
  1979. return -EINVAL;
  1980. mode->rotation_reflection = rotation;
  1981. return 0;
  1982. }
  1983. struct drm_named_mode {
  1984. const char *name;
  1985. unsigned int pixel_clock_khz;
  1986. unsigned int xres;
  1987. unsigned int yres;
  1988. unsigned int flags;
  1989. unsigned int tv_mode;
  1990. };
  1991. #define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode) \
  1992. { \
  1993. .name = _name, \
  1994. .pixel_clock_khz = _pclk, \
  1995. .xres = _x, \
  1996. .yres = _y, \
  1997. .flags = _flags, \
  1998. .tv_mode = _mode, \
  1999. }
  2000. static const struct drm_named_mode drm_named_modes[] = {
  2001. NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC),
  2002. NAMED_MODE("NTSC-J", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC_J),
  2003. NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL),
  2004. NAMED_MODE("PAL-M", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL_M),
  2005. };
  2006. static int drm_mode_parse_cmdline_named_mode(const char *name,
  2007. unsigned int name_end,
  2008. struct drm_cmdline_mode *cmdline_mode)
  2009. {
  2010. unsigned int i;
  2011. if (!name_end)
  2012. return 0;
  2013. /* If the name starts with a digit, it's not a named mode */
  2014. if (isdigit(name[0]))
  2015. return 0;
  2016. /*
  2017. * If there's an equal sign in the name, the command-line
  2018. * contains only an option and no mode.
  2019. */
  2020. if (strnchr(name, name_end, '='))
  2021. return 0;
  2022. /* The connection status extras can be set without a mode. */
  2023. if (name_end == 1 &&
  2024. (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
  2025. return 0;
  2026. /*
  2027. * We're sure we're a named mode at this point, iterate over the
  2028. * list of modes we're aware of.
  2029. */
  2030. for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
  2031. const struct drm_named_mode *mode = &drm_named_modes[i];
  2032. int ret;
  2033. ret = str_has_prefix(name, mode->name);
  2034. if (ret != name_end)
  2035. continue;
  2036. strscpy(cmdline_mode->name, mode->name, sizeof(cmdline_mode->name));
  2037. cmdline_mode->pixel_clock = mode->pixel_clock_khz;
  2038. cmdline_mode->xres = mode->xres;
  2039. cmdline_mode->yres = mode->yres;
  2040. cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
  2041. cmdline_mode->tv_mode = mode->tv_mode;
  2042. cmdline_mode->tv_mode_specified = true;
  2043. cmdline_mode->specified = true;
  2044. return 1;
  2045. }
  2046. return -EINVAL;
  2047. }
  2048. /**
  2049. * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
  2050. * @mode_option: optional per connector mode option
  2051. * @connector: connector to parse modeline for
  2052. * @mode: preallocated drm_cmdline_mode structure to fill out
  2053. *
  2054. * This parses @mode_option command line modeline for modes and options to
  2055. * configure the connector.
  2056. *
  2057. * This uses the same parameters as the fb modedb.c, except for an extra
  2058. * force-enable, force-enable-digital and force-disable bit at the end::
  2059. *
  2060. * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
  2061. *
  2062. * Additionals options can be provided following the mode, using a comma to
  2063. * separate each option. Valid options can be found in
  2064. * Documentation/fb/modedb.rst.
  2065. *
  2066. * The intermediate drm_cmdline_mode structure is required to store additional
  2067. * options from the command line modline like the force-enable/disable flag.
  2068. *
  2069. * Returns:
  2070. * True if a valid modeline has been parsed, false otherwise.
  2071. */
  2072. bool drm_mode_parse_command_line_for_connector(const char *mode_option,
  2073. const struct drm_connector *connector,
  2074. struct drm_cmdline_mode *mode)
  2075. {
  2076. const char *name;
  2077. bool freestanding = false, parse_extras = false;
  2078. unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
  2079. unsigned int mode_end = 0;
  2080. const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
  2081. const char *options_ptr = NULL;
  2082. char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
  2083. int len, ret;
  2084. memset(mode, 0, sizeof(*mode));
  2085. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
  2086. if (!mode_option)
  2087. return false;
  2088. name = mode_option;
  2089. /* Locate the start of named options */
  2090. options_ptr = strchr(name, ',');
  2091. if (options_ptr)
  2092. options_off = options_ptr - name;
  2093. else
  2094. options_off = strlen(name);
  2095. /* Try to locate the bpp and refresh specifiers, if any */
  2096. bpp_ptr = strnchr(name, options_off, '-');
  2097. while (bpp_ptr && !isdigit(bpp_ptr[1]))
  2098. bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
  2099. if (bpp_ptr)
  2100. bpp_off = bpp_ptr - name;
  2101. refresh_ptr = strnchr(name, options_off, '@');
  2102. if (refresh_ptr)
  2103. refresh_off = refresh_ptr - name;
  2104. /* Locate the end of the name / resolution, and parse it */
  2105. if (bpp_ptr) {
  2106. mode_end = bpp_off;
  2107. } else if (refresh_ptr) {
  2108. mode_end = refresh_off;
  2109. } else if (options_ptr) {
  2110. mode_end = options_off;
  2111. parse_extras = true;
  2112. } else {
  2113. mode_end = strlen(name);
  2114. parse_extras = true;
  2115. }
  2116. if (!mode_end)
  2117. return false;
  2118. ret = drm_mode_parse_cmdline_named_mode(name, mode_end, mode);
  2119. if (ret < 0)
  2120. return false;
  2121. /*
  2122. * Having a mode that starts by a letter (and thus is named) and
  2123. * an at-sign (used to specify a refresh rate) is disallowed.
  2124. */
  2125. if (ret && refresh_ptr)
  2126. return false;
  2127. /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
  2128. if (!mode->specified && isdigit(name[0])) {
  2129. ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
  2130. parse_extras,
  2131. connector,
  2132. mode);
  2133. if (ret)
  2134. return false;
  2135. mode->specified = true;
  2136. }
  2137. /* No mode? Check for freestanding extras and/or options */
  2138. if (!mode->specified) {
  2139. unsigned int len = strlen(mode_option);
  2140. if (bpp_ptr || refresh_ptr)
  2141. return false; /* syntax error */
  2142. if (len == 1 || (len >= 2 && mode_option[1] == ','))
  2143. extra_ptr = mode_option;
  2144. else
  2145. options_ptr = mode_option - 1;
  2146. freestanding = true;
  2147. }
  2148. if (bpp_ptr) {
  2149. ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
  2150. if (ret)
  2151. return false;
  2152. mode->bpp_specified = true;
  2153. }
  2154. if (refresh_ptr) {
  2155. ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
  2156. &refresh_end_ptr, mode);
  2157. if (ret)
  2158. return false;
  2159. mode->refresh_specified = true;
  2160. }
  2161. /*
  2162. * Locate the end of the bpp / refresh, and parse the extras
  2163. * if relevant
  2164. */
  2165. if (bpp_ptr && refresh_ptr)
  2166. extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
  2167. else if (bpp_ptr)
  2168. extra_ptr = bpp_end_ptr;
  2169. else if (refresh_ptr)
  2170. extra_ptr = refresh_end_ptr;
  2171. if (extra_ptr) {
  2172. if (options_ptr)
  2173. len = options_ptr - extra_ptr;
  2174. else
  2175. len = strlen(extra_ptr);
  2176. ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
  2177. connector, mode);
  2178. if (ret)
  2179. return false;
  2180. }
  2181. if (options_ptr) {
  2182. ret = drm_mode_parse_cmdline_options(options_ptr + 1,
  2183. freestanding,
  2184. connector, mode);
  2185. if (ret)
  2186. return false;
  2187. }
  2188. return true;
  2189. }
  2190. EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
  2191. static struct drm_display_mode *drm_named_mode(struct drm_device *dev,
  2192. struct drm_cmdline_mode *cmd)
  2193. {
  2194. unsigned int i;
  2195. for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
  2196. const struct drm_named_mode *named_mode = &drm_named_modes[i];
  2197. if (strcmp(cmd->name, named_mode->name))
  2198. continue;
  2199. if (!cmd->tv_mode_specified)
  2200. continue;
  2201. return drm_analog_tv_mode(dev,
  2202. named_mode->tv_mode,
  2203. named_mode->pixel_clock_khz * 1000,
  2204. named_mode->xres,
  2205. named_mode->yres,
  2206. named_mode->flags & DRM_MODE_FLAG_INTERLACE);
  2207. }
  2208. return NULL;
  2209. }
  2210. /**
  2211. * drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
  2212. * @dev: DRM device to create the new mode for
  2213. * @cmd: input command line modeline
  2214. *
  2215. * Returns:
  2216. * Pointer to converted mode on success, NULL on error.
  2217. */
  2218. struct drm_display_mode *
  2219. drm_mode_create_from_cmdline_mode(struct drm_device *dev,
  2220. struct drm_cmdline_mode *cmd)
  2221. {
  2222. struct drm_display_mode *mode;
  2223. if (cmd->xres == 0 || cmd->yres == 0)
  2224. return NULL;
  2225. if (strlen(cmd->name))
  2226. mode = drm_named_mode(dev, cmd);
  2227. else if (cmd->cvt)
  2228. mode = drm_cvt_mode(dev,
  2229. cmd->xres, cmd->yres,
  2230. cmd->refresh_specified ? cmd->refresh : 60,
  2231. cmd->rb, cmd->interlace,
  2232. cmd->margins);
  2233. else
  2234. mode = drm_gtf_mode(dev,
  2235. cmd->xres, cmd->yres,
  2236. cmd->refresh_specified ? cmd->refresh : 60,
  2237. cmd->interlace,
  2238. cmd->margins);
  2239. if (!mode)
  2240. return NULL;
  2241. mode->type |= DRM_MODE_TYPE_USERDEF;
  2242. /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
  2243. if (cmd->xres == 1366)
  2244. drm_mode_fixup_1366x768(mode);
  2245. drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
  2246. return mode;
  2247. }
  2248. EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
  2249. /**
  2250. * drm_mode_convert_to_umode - convert a drm_display_mode into a modeinfo
  2251. * @out: drm_mode_modeinfo struct to return to the user
  2252. * @in: drm_display_mode to use
  2253. *
  2254. * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
  2255. * the user.
  2256. */
  2257. void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
  2258. const struct drm_display_mode *in)
  2259. {
  2260. out->clock = in->clock;
  2261. out->hdisplay = in->hdisplay;
  2262. out->hsync_start = in->hsync_start;
  2263. out->hsync_end = in->hsync_end;
  2264. out->htotal = in->htotal;
  2265. out->hskew = in->hskew;
  2266. out->vdisplay = in->vdisplay;
  2267. out->vsync_start = in->vsync_start;
  2268. out->vsync_end = in->vsync_end;
  2269. out->vtotal = in->vtotal;
  2270. out->vscan = in->vscan;
  2271. out->vrefresh = drm_mode_vrefresh(in);
  2272. out->flags = in->flags;
  2273. out->type = in->type;
  2274. switch (in->picture_aspect_ratio) {
  2275. case HDMI_PICTURE_ASPECT_4_3:
  2276. out->flags |= DRM_MODE_FLAG_PIC_AR_4_3;
  2277. break;
  2278. case HDMI_PICTURE_ASPECT_16_9:
  2279. out->flags |= DRM_MODE_FLAG_PIC_AR_16_9;
  2280. break;
  2281. case HDMI_PICTURE_ASPECT_64_27:
  2282. out->flags |= DRM_MODE_FLAG_PIC_AR_64_27;
  2283. break;
  2284. case HDMI_PICTURE_ASPECT_256_135:
  2285. out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
  2286. break;
  2287. default:
  2288. WARN(1, "Invalid aspect ratio (0%x) on mode\n",
  2289. in->picture_aspect_ratio);
  2290. fallthrough;
  2291. case HDMI_PICTURE_ASPECT_NONE:
  2292. out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
  2293. break;
  2294. }
  2295. strscpy_pad(out->name, in->name, sizeof(out->name));
  2296. }
  2297. /**
  2298. * drm_mode_convert_umode - convert a modeinfo into a drm_display_mode
  2299. * @dev: drm device
  2300. * @out: drm_display_mode to return to the user
  2301. * @in: drm_mode_modeinfo to use
  2302. *
  2303. * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
  2304. * the caller.
  2305. *
  2306. * Returns:
  2307. * Zero on success, negative errno on failure.
  2308. */
  2309. int drm_mode_convert_umode(struct drm_device *dev,
  2310. struct drm_display_mode *out,
  2311. const struct drm_mode_modeinfo *in)
  2312. {
  2313. if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
  2314. return -ERANGE;
  2315. out->clock = in->clock;
  2316. out->hdisplay = in->hdisplay;
  2317. out->hsync_start = in->hsync_start;
  2318. out->hsync_end = in->hsync_end;
  2319. out->htotal = in->htotal;
  2320. out->hskew = in->hskew;
  2321. out->vdisplay = in->vdisplay;
  2322. out->vsync_start = in->vsync_start;
  2323. out->vsync_end = in->vsync_end;
  2324. out->vtotal = in->vtotal;
  2325. out->vscan = in->vscan;
  2326. out->flags = in->flags;
  2327. /*
  2328. * Old xf86-video-vmware (possibly others too) used to
  2329. * leave 'type' uninitialized. Just ignore any bits we
  2330. * don't like. It's a just hint after all, and more
  2331. * useful for the kernel->userspace direction anyway.
  2332. */
  2333. out->type = in->type & DRM_MODE_TYPE_ALL;
  2334. strscpy_pad(out->name, in->name, sizeof(out->name));
  2335. /* Clearing picture aspect ratio bits from out flags,
  2336. * as the aspect-ratio information is not stored in
  2337. * flags for kernel-mode, but in picture_aspect_ratio.
  2338. */
  2339. out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
  2340. switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
  2341. case DRM_MODE_FLAG_PIC_AR_4_3:
  2342. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
  2343. break;
  2344. case DRM_MODE_FLAG_PIC_AR_16_9:
  2345. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
  2346. break;
  2347. case DRM_MODE_FLAG_PIC_AR_64_27:
  2348. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27;
  2349. break;
  2350. case DRM_MODE_FLAG_PIC_AR_256_135:
  2351. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135;
  2352. break;
  2353. case DRM_MODE_FLAG_PIC_AR_NONE:
  2354. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
  2355. break;
  2356. default:
  2357. return -EINVAL;
  2358. }
  2359. out->status = drm_mode_validate_driver(dev, out);
  2360. if (out->status != MODE_OK)
  2361. return -EINVAL;
  2362. drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
  2363. return 0;
  2364. }
  2365. /**
  2366. * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
  2367. * output format
  2368. *
  2369. * @display: display under action
  2370. * @mode: video mode to be tested.
  2371. *
  2372. * Returns:
  2373. * true if the mode can be supported in YCBCR420 format
  2374. * false if not.
  2375. */
  2376. bool drm_mode_is_420_only(const struct drm_display_info *display,
  2377. const struct drm_display_mode *mode)
  2378. {
  2379. u8 vic = drm_match_cea_mode(mode);
  2380. return test_bit(vic, display->hdmi.y420_vdb_modes);
  2381. }
  2382. EXPORT_SYMBOL(drm_mode_is_420_only);
  2383. /**
  2384. * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
  2385. * output format also (along with RGB/YCBCR444/422)
  2386. *
  2387. * @display: display under action.
  2388. * @mode: video mode to be tested.
  2389. *
  2390. * Returns:
  2391. * true if the mode can be support YCBCR420 format
  2392. * false if not.
  2393. */
  2394. bool drm_mode_is_420_also(const struct drm_display_info *display,
  2395. const struct drm_display_mode *mode)
  2396. {
  2397. u8 vic = drm_match_cea_mode(mode);
  2398. return test_bit(vic, display->hdmi.y420_cmdb_modes);
  2399. }
  2400. EXPORT_SYMBOL(drm_mode_is_420_also);
  2401. /**
  2402. * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
  2403. * output format
  2404. *
  2405. * @display: display under action.
  2406. * @mode: video mode to be tested.
  2407. *
  2408. * Returns:
  2409. * true if the mode can be supported in YCBCR420 format
  2410. * false if not.
  2411. */
  2412. bool drm_mode_is_420(const struct drm_display_info *display,
  2413. const struct drm_display_mode *mode)
  2414. {
  2415. return drm_mode_is_420_only(display, mode) ||
  2416. drm_mode_is_420_also(display, mode);
  2417. }
  2418. EXPORT_SYMBOL(drm_mode_is_420);
  2419. /**
  2420. * drm_set_preferred_mode - Sets the preferred mode of a connector
  2421. * @connector: connector whose mode list should be processed
  2422. * @hpref: horizontal resolution of preferred mode
  2423. * @vpref: vertical resolution of preferred mode
  2424. *
  2425. * Marks a mode as preferred if it matches the resolution specified by @hpref
  2426. * and @vpref.
  2427. */
  2428. void drm_set_preferred_mode(struct drm_connector *connector,
  2429. int hpref, int vpref)
  2430. {
  2431. struct drm_display_mode *mode;
  2432. list_for_each_entry(mode, &connector->probed_modes, head) {
  2433. if (mode->hdisplay == hpref &&
  2434. mode->vdisplay == vpref)
  2435. mode->type |= DRM_MODE_TYPE_PREFERRED;
  2436. }
  2437. }
  2438. EXPORT_SYMBOL(drm_set_preferred_mode);