drm_modes.c 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778
  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_obj(struct drm_display_mode);
  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.
  1145. */
  1146. int drm_mode_vrefresh(const struct drm_display_mode *mode)
  1147. {
  1148. unsigned int num = 1, den = 1;
  1149. if (mode->htotal == 0 || mode->vtotal == 0)
  1150. return 0;
  1151. if (mode->flags & DRM_MODE_FLAG_INTERLACE)
  1152. num *= 2;
  1153. if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
  1154. den *= 2;
  1155. if (mode->vscan > 1)
  1156. den *= mode->vscan;
  1157. if (check_mul_overflow(mode->clock, num, &num))
  1158. return 0;
  1159. if (check_mul_overflow(mode->htotal * mode->vtotal, den, &den))
  1160. return 0;
  1161. return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
  1162. }
  1163. EXPORT_SYMBOL(drm_mode_vrefresh);
  1164. /**
  1165. * drm_mode_get_hv_timing - Fetches hdisplay/vdisplay for given mode
  1166. * @mode: mode to query
  1167. * @hdisplay: hdisplay value to fill in
  1168. * @vdisplay: vdisplay value to fill in
  1169. *
  1170. * The vdisplay value will be doubled if the specified mode is a stereo mode of
  1171. * the appropriate layout.
  1172. */
  1173. void drm_mode_get_hv_timing(const struct drm_display_mode *mode,
  1174. int *hdisplay, int *vdisplay)
  1175. {
  1176. struct drm_display_mode adjusted;
  1177. drm_mode_init(&adjusted, mode);
  1178. drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
  1179. *hdisplay = adjusted.crtc_hdisplay;
  1180. *vdisplay = adjusted.crtc_vdisplay;
  1181. }
  1182. EXPORT_SYMBOL(drm_mode_get_hv_timing);
  1183. /**
  1184. * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
  1185. * @p: mode
  1186. * @adjust_flags: a combination of adjustment flags
  1187. *
  1188. * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
  1189. *
  1190. * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
  1191. * interlaced modes.
  1192. * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
  1193. * buffers containing two eyes (only adjust the timings when needed, eg. for
  1194. * "frame packing" or "side by side full").
  1195. * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
  1196. * be performed for doublescan and vscan > 1 modes respectively.
  1197. */
  1198. void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
  1199. {
  1200. if (!p)
  1201. return;
  1202. p->crtc_clock = p->clock;
  1203. p->crtc_hdisplay = p->hdisplay;
  1204. p->crtc_hsync_start = p->hsync_start;
  1205. p->crtc_hsync_end = p->hsync_end;
  1206. p->crtc_htotal = p->htotal;
  1207. p->crtc_hskew = p->hskew;
  1208. p->crtc_vdisplay = p->vdisplay;
  1209. p->crtc_vsync_start = p->vsync_start;
  1210. p->crtc_vsync_end = p->vsync_end;
  1211. p->crtc_vtotal = p->vtotal;
  1212. if (p->flags & DRM_MODE_FLAG_INTERLACE) {
  1213. if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
  1214. p->crtc_vdisplay /= 2;
  1215. p->crtc_vsync_start /= 2;
  1216. p->crtc_vsync_end /= 2;
  1217. p->crtc_vtotal /= 2;
  1218. }
  1219. }
  1220. if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
  1221. if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
  1222. p->crtc_vdisplay *= 2;
  1223. p->crtc_vsync_start *= 2;
  1224. p->crtc_vsync_end *= 2;
  1225. p->crtc_vtotal *= 2;
  1226. }
  1227. }
  1228. if (!(adjust_flags & CRTC_NO_VSCAN)) {
  1229. if (p->vscan > 1) {
  1230. p->crtc_vdisplay *= p->vscan;
  1231. p->crtc_vsync_start *= p->vscan;
  1232. p->crtc_vsync_end *= p->vscan;
  1233. p->crtc_vtotal *= p->vscan;
  1234. }
  1235. }
  1236. if (adjust_flags & CRTC_STEREO_DOUBLE) {
  1237. unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
  1238. switch (layout) {
  1239. case DRM_MODE_FLAG_3D_FRAME_PACKING:
  1240. p->crtc_clock *= 2;
  1241. p->crtc_vdisplay += p->crtc_vtotal;
  1242. p->crtc_vsync_start += p->crtc_vtotal;
  1243. p->crtc_vsync_end += p->crtc_vtotal;
  1244. p->crtc_vtotal += p->crtc_vtotal;
  1245. break;
  1246. }
  1247. }
  1248. p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
  1249. p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
  1250. p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
  1251. p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
  1252. }
  1253. EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  1254. /**
  1255. * drm_mode_copy - copy the mode
  1256. * @dst: mode to overwrite
  1257. * @src: mode to copy
  1258. *
  1259. * Copy an existing mode into another mode, preserving the
  1260. * list head of the destination mode.
  1261. */
  1262. void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
  1263. {
  1264. struct list_head head = dst->head;
  1265. *dst = *src;
  1266. dst->head = head;
  1267. }
  1268. EXPORT_SYMBOL(drm_mode_copy);
  1269. /**
  1270. * drm_mode_init - initialize the mode from another mode
  1271. * @dst: mode to overwrite
  1272. * @src: mode to copy
  1273. *
  1274. * Copy an existing mode into another mode, zeroing the
  1275. * list head of the destination mode. Typically used
  1276. * to guarantee the list head is not left with stack
  1277. * garbage in on-stack modes.
  1278. */
  1279. void drm_mode_init(struct drm_display_mode *dst, const struct drm_display_mode *src)
  1280. {
  1281. memset(dst, 0, sizeof(*dst));
  1282. drm_mode_copy(dst, src);
  1283. }
  1284. EXPORT_SYMBOL(drm_mode_init);
  1285. /**
  1286. * drm_mode_duplicate - allocate and duplicate an existing mode
  1287. * @dev: drm_device to allocate the duplicated mode for
  1288. * @mode: mode to duplicate
  1289. *
  1290. * Just allocate a new mode, copy the existing mode into it, and return
  1291. * a pointer to it. Used to create new instances of established modes.
  1292. *
  1293. * Returns:
  1294. * Pointer to duplicated mode on success, NULL on error.
  1295. */
  1296. struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
  1297. const struct drm_display_mode *mode)
  1298. {
  1299. struct drm_display_mode *nmode;
  1300. nmode = drm_mode_create(dev);
  1301. if (!nmode)
  1302. return NULL;
  1303. drm_mode_copy(nmode, mode);
  1304. return nmode;
  1305. }
  1306. EXPORT_SYMBOL(drm_mode_duplicate);
  1307. static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
  1308. const struct drm_display_mode *mode2)
  1309. {
  1310. return mode1->hdisplay == mode2->hdisplay &&
  1311. mode1->hsync_start == mode2->hsync_start &&
  1312. mode1->hsync_end == mode2->hsync_end &&
  1313. mode1->htotal == mode2->htotal &&
  1314. mode1->hskew == mode2->hskew &&
  1315. mode1->vdisplay == mode2->vdisplay &&
  1316. mode1->vsync_start == mode2->vsync_start &&
  1317. mode1->vsync_end == mode2->vsync_end &&
  1318. mode1->vtotal == mode2->vtotal &&
  1319. mode1->vscan == mode2->vscan;
  1320. }
  1321. static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
  1322. const struct drm_display_mode *mode2)
  1323. {
  1324. /*
  1325. * do clock check convert to PICOS
  1326. * so fb modes get matched the same
  1327. */
  1328. if (mode1->clock && mode2->clock)
  1329. return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
  1330. else
  1331. return mode1->clock == mode2->clock;
  1332. }
  1333. static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
  1334. const struct drm_display_mode *mode2)
  1335. {
  1336. return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
  1337. (mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
  1338. }
  1339. static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
  1340. const struct drm_display_mode *mode2)
  1341. {
  1342. return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
  1343. (mode2->flags & DRM_MODE_FLAG_3D_MASK);
  1344. }
  1345. static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
  1346. const struct drm_display_mode *mode2)
  1347. {
  1348. return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
  1349. }
  1350. /**
  1351. * drm_mode_match - test modes for (partial) equality
  1352. * @mode1: first mode
  1353. * @mode2: second mode
  1354. * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
  1355. *
  1356. * Check to see if @mode1 and @mode2 are equivalent.
  1357. *
  1358. * Returns:
  1359. * True if the modes are (partially) equal, false otherwise.
  1360. */
  1361. bool drm_mode_match(const struct drm_display_mode *mode1,
  1362. const struct drm_display_mode *mode2,
  1363. unsigned int match_flags)
  1364. {
  1365. if (!mode1 && !mode2)
  1366. return true;
  1367. if (!mode1 || !mode2)
  1368. return false;
  1369. if (match_flags & DRM_MODE_MATCH_TIMINGS &&
  1370. !drm_mode_match_timings(mode1, mode2))
  1371. return false;
  1372. if (match_flags & DRM_MODE_MATCH_CLOCK &&
  1373. !drm_mode_match_clock(mode1, mode2))
  1374. return false;
  1375. if (match_flags & DRM_MODE_MATCH_FLAGS &&
  1376. !drm_mode_match_flags(mode1, mode2))
  1377. return false;
  1378. if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
  1379. !drm_mode_match_3d_flags(mode1, mode2))
  1380. return false;
  1381. if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
  1382. !drm_mode_match_aspect_ratio(mode1, mode2))
  1383. return false;
  1384. return true;
  1385. }
  1386. EXPORT_SYMBOL(drm_mode_match);
  1387. /**
  1388. * drm_mode_equal - test modes for equality
  1389. * @mode1: first mode
  1390. * @mode2: second mode
  1391. *
  1392. * Check to see if @mode1 and @mode2 are equivalent.
  1393. *
  1394. * Returns:
  1395. * True if the modes are equal, false otherwise.
  1396. */
  1397. bool drm_mode_equal(const struct drm_display_mode *mode1,
  1398. const struct drm_display_mode *mode2)
  1399. {
  1400. return drm_mode_match(mode1, mode2,
  1401. DRM_MODE_MATCH_TIMINGS |
  1402. DRM_MODE_MATCH_CLOCK |
  1403. DRM_MODE_MATCH_FLAGS |
  1404. DRM_MODE_MATCH_3D_FLAGS|
  1405. DRM_MODE_MATCH_ASPECT_RATIO);
  1406. }
  1407. EXPORT_SYMBOL(drm_mode_equal);
  1408. /**
  1409. * drm_mode_equal_no_clocks - test modes for equality
  1410. * @mode1: first mode
  1411. * @mode2: second mode
  1412. *
  1413. * Check to see if @mode1 and @mode2 are equivalent, but
  1414. * don't check the pixel clocks.
  1415. *
  1416. * Returns:
  1417. * True if the modes are equal, false otherwise.
  1418. */
  1419. bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
  1420. const struct drm_display_mode *mode2)
  1421. {
  1422. return drm_mode_match(mode1, mode2,
  1423. DRM_MODE_MATCH_TIMINGS |
  1424. DRM_MODE_MATCH_FLAGS |
  1425. DRM_MODE_MATCH_3D_FLAGS);
  1426. }
  1427. EXPORT_SYMBOL(drm_mode_equal_no_clocks);
  1428. /**
  1429. * drm_mode_equal_no_clocks_no_stereo - test modes for equality
  1430. * @mode1: first mode
  1431. * @mode2: second mode
  1432. *
  1433. * Check to see if @mode1 and @mode2 are equivalent, but
  1434. * don't check the pixel clocks nor the stereo layout.
  1435. *
  1436. * Returns:
  1437. * True if the modes are equal, false otherwise.
  1438. */
  1439. bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
  1440. const struct drm_display_mode *mode2)
  1441. {
  1442. return drm_mode_match(mode1, mode2,
  1443. DRM_MODE_MATCH_TIMINGS |
  1444. DRM_MODE_MATCH_FLAGS);
  1445. }
  1446. EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
  1447. static enum drm_mode_status
  1448. drm_mode_validate_basic(const struct drm_display_mode *mode)
  1449. {
  1450. if (mode->type & ~DRM_MODE_TYPE_ALL)
  1451. return MODE_BAD;
  1452. if (mode->flags & ~DRM_MODE_FLAG_ALL)
  1453. return MODE_BAD;
  1454. if ((mode->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
  1455. return MODE_BAD;
  1456. if (mode->clock == 0)
  1457. return MODE_CLOCK_LOW;
  1458. if (mode->hdisplay == 0 ||
  1459. mode->hsync_start < mode->hdisplay ||
  1460. mode->hsync_end < mode->hsync_start ||
  1461. mode->htotal < mode->hsync_end)
  1462. return MODE_H_ILLEGAL;
  1463. if (mode->vdisplay == 0 ||
  1464. mode->vsync_start < mode->vdisplay ||
  1465. mode->vsync_end < mode->vsync_start ||
  1466. mode->vtotal < mode->vsync_end)
  1467. return MODE_V_ILLEGAL;
  1468. return MODE_OK;
  1469. }
  1470. /**
  1471. * drm_mode_validate_driver - make sure the mode is somewhat sane
  1472. * @dev: drm device
  1473. * @mode: mode to check
  1474. *
  1475. * First do basic validation on the mode, and then allow the driver
  1476. * to check for device/driver specific limitations via the optional
  1477. * &drm_mode_config_helper_funcs.mode_valid hook.
  1478. *
  1479. * Returns:
  1480. * The mode status
  1481. */
  1482. enum drm_mode_status
  1483. drm_mode_validate_driver(struct drm_device *dev,
  1484. const struct drm_display_mode *mode)
  1485. {
  1486. enum drm_mode_status status;
  1487. status = drm_mode_validate_basic(mode);
  1488. if (status != MODE_OK)
  1489. return status;
  1490. if (dev->mode_config.funcs->mode_valid)
  1491. return dev->mode_config.funcs->mode_valid(dev, mode);
  1492. else
  1493. return MODE_OK;
  1494. }
  1495. EXPORT_SYMBOL(drm_mode_validate_driver);
  1496. /**
  1497. * drm_mode_validate_size - make sure modes adhere to size constraints
  1498. * @mode: mode to check
  1499. * @maxX: maximum width
  1500. * @maxY: maximum height
  1501. *
  1502. * This function is a helper which can be used to validate modes against size
  1503. * limitations of the DRM device/connector. If a mode is too big its status
  1504. * member is updated with the appropriate validation failure code. The list
  1505. * itself is not changed.
  1506. *
  1507. * Returns:
  1508. * The mode status
  1509. */
  1510. enum drm_mode_status
  1511. drm_mode_validate_size(const struct drm_display_mode *mode,
  1512. int maxX, int maxY)
  1513. {
  1514. if (maxX > 0 && mode->hdisplay > maxX)
  1515. return MODE_VIRTUAL_X;
  1516. if (maxY > 0 && mode->vdisplay > maxY)
  1517. return MODE_VIRTUAL_Y;
  1518. return MODE_OK;
  1519. }
  1520. EXPORT_SYMBOL(drm_mode_validate_size);
  1521. /**
  1522. * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
  1523. * @mode: mode to check
  1524. * @connector: drm connector under action
  1525. *
  1526. * This function is a helper which can be used to filter out any YCBCR420
  1527. * only mode, when the source doesn't support it.
  1528. *
  1529. * Returns:
  1530. * The mode status
  1531. */
  1532. enum drm_mode_status
  1533. drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
  1534. struct drm_connector *connector)
  1535. {
  1536. if (!connector->ycbcr_420_allowed &&
  1537. drm_mode_is_420_only(&connector->display_info, mode))
  1538. return MODE_NO_420;
  1539. return MODE_OK;
  1540. }
  1541. EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
  1542. #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
  1543. static const char * const drm_mode_status_names[] = {
  1544. MODE_STATUS(OK),
  1545. MODE_STATUS(HSYNC),
  1546. MODE_STATUS(VSYNC),
  1547. MODE_STATUS(H_ILLEGAL),
  1548. MODE_STATUS(V_ILLEGAL),
  1549. MODE_STATUS(BAD_WIDTH),
  1550. MODE_STATUS(NOMODE),
  1551. MODE_STATUS(NO_INTERLACE),
  1552. MODE_STATUS(NO_DBLESCAN),
  1553. MODE_STATUS(NO_VSCAN),
  1554. MODE_STATUS(MEM),
  1555. MODE_STATUS(VIRTUAL_X),
  1556. MODE_STATUS(VIRTUAL_Y),
  1557. MODE_STATUS(MEM_VIRT),
  1558. MODE_STATUS(NOCLOCK),
  1559. MODE_STATUS(CLOCK_HIGH),
  1560. MODE_STATUS(CLOCK_LOW),
  1561. MODE_STATUS(CLOCK_RANGE),
  1562. MODE_STATUS(BAD_HVALUE),
  1563. MODE_STATUS(BAD_VVALUE),
  1564. MODE_STATUS(BAD_VSCAN),
  1565. MODE_STATUS(HSYNC_NARROW),
  1566. MODE_STATUS(HSYNC_WIDE),
  1567. MODE_STATUS(HBLANK_NARROW),
  1568. MODE_STATUS(HBLANK_WIDE),
  1569. MODE_STATUS(VSYNC_NARROW),
  1570. MODE_STATUS(VSYNC_WIDE),
  1571. MODE_STATUS(VBLANK_NARROW),
  1572. MODE_STATUS(VBLANK_WIDE),
  1573. MODE_STATUS(PANEL),
  1574. MODE_STATUS(INTERLACE_WIDTH),
  1575. MODE_STATUS(ONE_WIDTH),
  1576. MODE_STATUS(ONE_HEIGHT),
  1577. MODE_STATUS(ONE_SIZE),
  1578. MODE_STATUS(NO_REDUCED),
  1579. MODE_STATUS(NO_STEREO),
  1580. MODE_STATUS(NO_420),
  1581. MODE_STATUS(STALE),
  1582. MODE_STATUS(BAD),
  1583. MODE_STATUS(ERROR),
  1584. };
  1585. #undef MODE_STATUS
  1586. const char *drm_get_mode_status_name(enum drm_mode_status status)
  1587. {
  1588. int index = status + 3;
  1589. if (WARN_ON(index < 0 || index >= ARRAY_SIZE(drm_mode_status_names)))
  1590. return "";
  1591. return drm_mode_status_names[index];
  1592. }
  1593. /**
  1594. * drm_mode_prune_invalid - remove invalid modes from mode list
  1595. * @dev: DRM device
  1596. * @mode_list: list of modes to check
  1597. * @verbose: be verbose about it
  1598. *
  1599. * This helper function can be used to prune a display mode list after
  1600. * validation has been completed. All modes whose status is not MODE_OK will be
  1601. * removed from the list, and if @verbose the status code and mode name is also
  1602. * printed to dmesg.
  1603. */
  1604. void drm_mode_prune_invalid(struct drm_device *dev,
  1605. struct list_head *mode_list, bool verbose)
  1606. {
  1607. struct drm_display_mode *mode, *t;
  1608. list_for_each_entry_safe(mode, t, mode_list, head) {
  1609. if (mode->status != MODE_OK) {
  1610. list_del(&mode->head);
  1611. if (mode->type & DRM_MODE_TYPE_USERDEF) {
  1612. drm_warn(dev, "User-defined mode not supported: "
  1613. DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
  1614. }
  1615. if (verbose) {
  1616. drm_dbg_kms(dev, "Rejected mode: " DRM_MODE_FMT " (%s)\n",
  1617. DRM_MODE_ARG(mode), drm_get_mode_status_name(mode->status));
  1618. }
  1619. drm_mode_destroy(dev, mode);
  1620. }
  1621. }
  1622. }
  1623. EXPORT_SYMBOL(drm_mode_prune_invalid);
  1624. /**
  1625. * drm_mode_compare - compare modes for favorability
  1626. * @priv: unused
  1627. * @lh_a: list_head for first mode
  1628. * @lh_b: list_head for second mode
  1629. *
  1630. * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
  1631. * which is better.
  1632. *
  1633. * Returns:
  1634. * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
  1635. * positive if @lh_b is better than @lh_a.
  1636. */
  1637. static int drm_mode_compare(void *priv, const struct list_head *lh_a,
  1638. const struct list_head *lh_b)
  1639. {
  1640. struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
  1641. struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
  1642. int diff;
  1643. diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
  1644. ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
  1645. if (diff)
  1646. return diff;
  1647. diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
  1648. if (diff)
  1649. return diff;
  1650. diff = drm_mode_vrefresh(b) - drm_mode_vrefresh(a);
  1651. if (diff)
  1652. return diff;
  1653. diff = b->clock - a->clock;
  1654. return diff;
  1655. }
  1656. /**
  1657. * drm_mode_sort - sort mode list
  1658. * @mode_list: list of drm_display_mode structures to sort
  1659. *
  1660. * Sort @mode_list by favorability, moving good modes to the head of the list.
  1661. */
  1662. void drm_mode_sort(struct list_head *mode_list)
  1663. {
  1664. list_sort(NULL, mode_list, drm_mode_compare);
  1665. }
  1666. EXPORT_SYMBOL(drm_mode_sort);
  1667. /**
  1668. * drm_connector_list_update - update the mode list for the connector
  1669. * @connector: the connector to update
  1670. *
  1671. * This moves the modes from the @connector probed_modes list
  1672. * to the actual mode list. It compares the probed mode against the current
  1673. * list and only adds different/new modes.
  1674. *
  1675. * This is just a helper functions doesn't validate any modes itself and also
  1676. * doesn't prune any invalid modes. Callers need to do that themselves.
  1677. */
  1678. void drm_connector_list_update(struct drm_connector *connector)
  1679. {
  1680. struct drm_display_mode *pmode, *pt;
  1681. WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
  1682. list_for_each_entry_safe(pmode, pt, &connector->probed_modes, head) {
  1683. struct drm_display_mode *mode;
  1684. bool found_it = false;
  1685. /* go through current modes checking for the new probed mode */
  1686. list_for_each_entry(mode, &connector->modes, head) {
  1687. if (!drm_mode_equal(pmode, mode))
  1688. continue;
  1689. found_it = true;
  1690. /*
  1691. * If the old matching mode is stale (ie. left over
  1692. * from a previous probe) just replace it outright.
  1693. * Otherwise just merge the type bits between all
  1694. * equal probed modes.
  1695. *
  1696. * If two probed modes are considered equal, pick the
  1697. * actual timings from the one that's marked as
  1698. * preferred (in case the match isn't 100%). If
  1699. * multiple or zero preferred modes are present, favor
  1700. * the mode added to the probed_modes list first.
  1701. */
  1702. if (mode->status == MODE_STALE) {
  1703. drm_mode_copy(mode, pmode);
  1704. } else if ((mode->type & DRM_MODE_TYPE_PREFERRED) == 0 &&
  1705. (pmode->type & DRM_MODE_TYPE_PREFERRED) != 0) {
  1706. pmode->type |= mode->type;
  1707. drm_mode_copy(mode, pmode);
  1708. } else {
  1709. mode->type |= pmode->type;
  1710. }
  1711. list_del(&pmode->head);
  1712. drm_mode_destroy(connector->dev, pmode);
  1713. break;
  1714. }
  1715. if (!found_it) {
  1716. list_move_tail(&pmode->head, &connector->modes);
  1717. }
  1718. }
  1719. }
  1720. EXPORT_SYMBOL(drm_connector_list_update);
  1721. static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
  1722. struct drm_cmdline_mode *mode)
  1723. {
  1724. unsigned int bpp;
  1725. if (str[0] != '-')
  1726. return -EINVAL;
  1727. str++;
  1728. bpp = simple_strtol(str, end_ptr, 10);
  1729. if (*end_ptr == str)
  1730. return -EINVAL;
  1731. mode->bpp = bpp;
  1732. mode->bpp_specified = true;
  1733. return 0;
  1734. }
  1735. static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
  1736. struct drm_cmdline_mode *mode)
  1737. {
  1738. unsigned int refresh;
  1739. if (str[0] != '@')
  1740. return -EINVAL;
  1741. str++;
  1742. refresh = simple_strtol(str, end_ptr, 10);
  1743. if (*end_ptr == str)
  1744. return -EINVAL;
  1745. mode->refresh = refresh;
  1746. mode->refresh_specified = true;
  1747. return 0;
  1748. }
  1749. static int drm_mode_parse_cmdline_extra(const char *str, int length,
  1750. bool freestanding,
  1751. const struct drm_connector *connector,
  1752. struct drm_cmdline_mode *mode)
  1753. {
  1754. int i;
  1755. for (i = 0; i < length; i++) {
  1756. switch (str[i]) {
  1757. case 'i':
  1758. if (freestanding)
  1759. return -EINVAL;
  1760. mode->interlace = true;
  1761. break;
  1762. case 'm':
  1763. if (freestanding)
  1764. return -EINVAL;
  1765. mode->margins = true;
  1766. break;
  1767. case 'D':
  1768. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1769. return -EINVAL;
  1770. if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
  1771. (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
  1772. mode->force = DRM_FORCE_ON;
  1773. else
  1774. mode->force = DRM_FORCE_ON_DIGITAL;
  1775. break;
  1776. case 'd':
  1777. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1778. return -EINVAL;
  1779. mode->force = DRM_FORCE_OFF;
  1780. break;
  1781. case 'e':
  1782. if (mode->force != DRM_FORCE_UNSPECIFIED)
  1783. return -EINVAL;
  1784. mode->force = DRM_FORCE_ON;
  1785. break;
  1786. default:
  1787. return -EINVAL;
  1788. }
  1789. }
  1790. return 0;
  1791. }
  1792. static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
  1793. bool extras,
  1794. const struct drm_connector *connector,
  1795. struct drm_cmdline_mode *mode)
  1796. {
  1797. const char *str_start = str;
  1798. bool rb = false, cvt = false;
  1799. int xres = 0, yres = 0;
  1800. int remaining, i;
  1801. char *end_ptr;
  1802. xres = simple_strtol(str, &end_ptr, 10);
  1803. if (end_ptr == str)
  1804. return -EINVAL;
  1805. if (end_ptr[0] != 'x')
  1806. return -EINVAL;
  1807. end_ptr++;
  1808. str = end_ptr;
  1809. yres = simple_strtol(str, &end_ptr, 10);
  1810. if (end_ptr == str)
  1811. return -EINVAL;
  1812. remaining = length - (end_ptr - str_start);
  1813. if (remaining < 0)
  1814. return -EINVAL;
  1815. for (i = 0; i < remaining; i++) {
  1816. switch (end_ptr[i]) {
  1817. case 'M':
  1818. cvt = true;
  1819. break;
  1820. case 'R':
  1821. rb = true;
  1822. break;
  1823. default:
  1824. /*
  1825. * Try to pass that to our extras parsing
  1826. * function to handle the case where the
  1827. * extras are directly after the resolution
  1828. */
  1829. if (extras) {
  1830. int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
  1831. 1,
  1832. false,
  1833. connector,
  1834. mode);
  1835. if (ret)
  1836. return ret;
  1837. } else {
  1838. return -EINVAL;
  1839. }
  1840. }
  1841. }
  1842. mode->xres = xres;
  1843. mode->yres = yres;
  1844. mode->cvt = cvt;
  1845. mode->rb = rb;
  1846. return 0;
  1847. }
  1848. static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
  1849. {
  1850. const char *value;
  1851. char *endp;
  1852. /*
  1853. * delim must point to the '=', otherwise it is a syntax error and
  1854. * if delim points to the terminating zero, then delim + 1 will point
  1855. * past the end of the string.
  1856. */
  1857. if (*delim != '=')
  1858. return -EINVAL;
  1859. value = delim + 1;
  1860. *int_ret = simple_strtol(value, &endp, 10);
  1861. /* Make sure we have parsed something */
  1862. if (endp == value)
  1863. return -EINVAL;
  1864. return 0;
  1865. }
  1866. static int drm_mode_parse_panel_orientation(const char *delim,
  1867. struct drm_cmdline_mode *mode)
  1868. {
  1869. const char *value;
  1870. if (*delim != '=')
  1871. return -EINVAL;
  1872. value = delim + 1;
  1873. delim = strchr(value, ',');
  1874. if (!delim)
  1875. delim = value + strlen(value);
  1876. if (!strncmp(value, "normal", delim - value))
  1877. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
  1878. else if (!strncmp(value, "upside_down", delim - value))
  1879. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
  1880. else if (!strncmp(value, "left_side_up", delim - value))
  1881. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
  1882. else if (!strncmp(value, "right_side_up", delim - value))
  1883. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
  1884. else
  1885. return -EINVAL;
  1886. return 0;
  1887. }
  1888. static int drm_mode_parse_tv_mode(const char *delim,
  1889. struct drm_cmdline_mode *mode)
  1890. {
  1891. const char *value;
  1892. int ret;
  1893. if (*delim != '=')
  1894. return -EINVAL;
  1895. value = delim + 1;
  1896. delim = strchr(value, ',');
  1897. if (!delim)
  1898. delim = value + strlen(value);
  1899. ret = drm_get_tv_mode_from_name(value, delim - value);
  1900. if (ret < 0)
  1901. return ret;
  1902. mode->tv_mode_specified = true;
  1903. mode->tv_mode = ret;
  1904. return 0;
  1905. }
  1906. static int drm_mode_parse_cmdline_options(const char *str,
  1907. bool freestanding,
  1908. const struct drm_connector *connector,
  1909. struct drm_cmdline_mode *mode)
  1910. {
  1911. unsigned int deg, margin, rotation = 0;
  1912. const char *delim, *option, *sep;
  1913. option = str;
  1914. do {
  1915. delim = strchr(option, '=');
  1916. if (!delim) {
  1917. delim = strchr(option, ',');
  1918. if (!delim)
  1919. delim = option + strlen(option);
  1920. }
  1921. if (!strncmp(option, "rotate", delim - option)) {
  1922. if (drm_mode_parse_cmdline_int(delim, &deg))
  1923. return -EINVAL;
  1924. switch (deg) {
  1925. case 0:
  1926. rotation |= DRM_MODE_ROTATE_0;
  1927. break;
  1928. case 90:
  1929. rotation |= DRM_MODE_ROTATE_90;
  1930. break;
  1931. case 180:
  1932. rotation |= DRM_MODE_ROTATE_180;
  1933. break;
  1934. case 270:
  1935. rotation |= DRM_MODE_ROTATE_270;
  1936. break;
  1937. default:
  1938. return -EINVAL;
  1939. }
  1940. } else if (!strncmp(option, "reflect_x", delim - option)) {
  1941. rotation |= DRM_MODE_REFLECT_X;
  1942. } else if (!strncmp(option, "reflect_y", delim - option)) {
  1943. rotation |= DRM_MODE_REFLECT_Y;
  1944. } else if (!strncmp(option, "margin_right", delim - option)) {
  1945. if (drm_mode_parse_cmdline_int(delim, &margin))
  1946. return -EINVAL;
  1947. mode->tv_margins.right = margin;
  1948. } else if (!strncmp(option, "margin_left", delim - option)) {
  1949. if (drm_mode_parse_cmdline_int(delim, &margin))
  1950. return -EINVAL;
  1951. mode->tv_margins.left = margin;
  1952. } else if (!strncmp(option, "margin_top", delim - option)) {
  1953. if (drm_mode_parse_cmdline_int(delim, &margin))
  1954. return -EINVAL;
  1955. mode->tv_margins.top = margin;
  1956. } else if (!strncmp(option, "margin_bottom", delim - option)) {
  1957. if (drm_mode_parse_cmdline_int(delim, &margin))
  1958. return -EINVAL;
  1959. mode->tv_margins.bottom = margin;
  1960. } else if (!strncmp(option, "panel_orientation", delim - option)) {
  1961. if (drm_mode_parse_panel_orientation(delim, mode))
  1962. return -EINVAL;
  1963. } else if (!strncmp(option, "tv_mode", delim - option)) {
  1964. if (drm_mode_parse_tv_mode(delim, mode))
  1965. return -EINVAL;
  1966. } else {
  1967. return -EINVAL;
  1968. }
  1969. sep = strchr(delim, ',');
  1970. option = sep + 1;
  1971. } while (sep);
  1972. if (rotation && freestanding)
  1973. return -EINVAL;
  1974. if (!(rotation & DRM_MODE_ROTATE_MASK))
  1975. rotation |= DRM_MODE_ROTATE_0;
  1976. /* Make sure there is exactly one rotation defined */
  1977. if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
  1978. return -EINVAL;
  1979. mode->rotation_reflection = rotation;
  1980. return 0;
  1981. }
  1982. struct drm_named_mode {
  1983. const char *name;
  1984. unsigned int pixel_clock_khz;
  1985. unsigned int xres;
  1986. unsigned int yres;
  1987. unsigned int flags;
  1988. unsigned int tv_mode;
  1989. };
  1990. #define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode) \
  1991. { \
  1992. .name = _name, \
  1993. .pixel_clock_khz = _pclk, \
  1994. .xres = _x, \
  1995. .yres = _y, \
  1996. .flags = _flags, \
  1997. .tv_mode = _mode, \
  1998. }
  1999. static const struct drm_named_mode drm_named_modes[] = {
  2000. NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC),
  2001. NAMED_MODE("NTSC-J", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC_J),
  2002. NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL),
  2003. NAMED_MODE("PAL-M", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL_M),
  2004. };
  2005. static int drm_mode_parse_cmdline_named_mode(const char *name,
  2006. unsigned int name_end,
  2007. struct drm_cmdline_mode *cmdline_mode)
  2008. {
  2009. unsigned int i;
  2010. if (!name_end)
  2011. return 0;
  2012. /* If the name starts with a digit, it's not a named mode */
  2013. if (isdigit(name[0]))
  2014. return 0;
  2015. /*
  2016. * If there's an equal sign in the name, the command-line
  2017. * contains only an option and no mode.
  2018. */
  2019. if (strnchr(name, name_end, '='))
  2020. return 0;
  2021. /* The connection status extras can be set without a mode. */
  2022. if (name_end == 1 &&
  2023. (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
  2024. return 0;
  2025. /*
  2026. * We're sure we're a named mode at this point, iterate over the
  2027. * list of modes we're aware of.
  2028. */
  2029. for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
  2030. const struct drm_named_mode *mode = &drm_named_modes[i];
  2031. int ret;
  2032. ret = str_has_prefix(name, mode->name);
  2033. if (ret != name_end)
  2034. continue;
  2035. strscpy(cmdline_mode->name, mode->name, sizeof(cmdline_mode->name));
  2036. cmdline_mode->pixel_clock = mode->pixel_clock_khz;
  2037. cmdline_mode->xres = mode->xres;
  2038. cmdline_mode->yres = mode->yres;
  2039. cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
  2040. cmdline_mode->tv_mode = mode->tv_mode;
  2041. cmdline_mode->tv_mode_specified = true;
  2042. cmdline_mode->specified = true;
  2043. return 1;
  2044. }
  2045. return -EINVAL;
  2046. }
  2047. /**
  2048. * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
  2049. * @mode_option: optional per connector mode option
  2050. * @connector: connector to parse modeline for
  2051. * @mode: preallocated drm_cmdline_mode structure to fill out
  2052. *
  2053. * This parses @mode_option command line modeline for modes and options to
  2054. * configure the connector.
  2055. *
  2056. * This uses the same parameters as the fb modedb.c, except for an extra
  2057. * force-enable, force-enable-digital and force-disable bit at the end::
  2058. *
  2059. * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
  2060. *
  2061. * Additionals options can be provided following the mode, using a comma to
  2062. * separate each option. Valid options can be found in
  2063. * Documentation/fb/modedb.rst.
  2064. *
  2065. * The intermediate drm_cmdline_mode structure is required to store additional
  2066. * options from the command line modline like the force-enable/disable flag.
  2067. *
  2068. * Returns:
  2069. * True if a valid modeline has been parsed, false otherwise.
  2070. */
  2071. bool drm_mode_parse_command_line_for_connector(const char *mode_option,
  2072. const struct drm_connector *connector,
  2073. struct drm_cmdline_mode *mode)
  2074. {
  2075. const char *name;
  2076. bool freestanding = false, parse_extras = false;
  2077. unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
  2078. unsigned int mode_end = 0;
  2079. const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
  2080. const char *options_ptr = NULL;
  2081. char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
  2082. int len, ret;
  2083. memset(mode, 0, sizeof(*mode));
  2084. mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
  2085. if (!mode_option)
  2086. return false;
  2087. name = mode_option;
  2088. /* Locate the start of named options */
  2089. options_ptr = strchr(name, ',');
  2090. if (options_ptr)
  2091. options_off = options_ptr - name;
  2092. else
  2093. options_off = strlen(name);
  2094. /* Try to locate the bpp and refresh specifiers, if any */
  2095. bpp_ptr = strnchr(name, options_off, '-');
  2096. while (bpp_ptr && !isdigit(bpp_ptr[1]))
  2097. bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
  2098. if (bpp_ptr)
  2099. bpp_off = bpp_ptr - name;
  2100. refresh_ptr = strnchr(name, options_off, '@');
  2101. if (refresh_ptr)
  2102. refresh_off = refresh_ptr - name;
  2103. /* Locate the end of the name / resolution, and parse it */
  2104. if (bpp_ptr) {
  2105. mode_end = bpp_off;
  2106. } else if (refresh_ptr) {
  2107. mode_end = refresh_off;
  2108. } else if (options_ptr) {
  2109. mode_end = options_off;
  2110. parse_extras = true;
  2111. } else {
  2112. mode_end = strlen(name);
  2113. parse_extras = true;
  2114. }
  2115. if (!mode_end)
  2116. return false;
  2117. ret = drm_mode_parse_cmdline_named_mode(name, mode_end, mode);
  2118. if (ret < 0)
  2119. return false;
  2120. /*
  2121. * Having a mode that starts by a letter (and thus is named) and
  2122. * an at-sign (used to specify a refresh rate) is disallowed.
  2123. */
  2124. if (ret && refresh_ptr)
  2125. return false;
  2126. /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
  2127. if (!mode->specified && isdigit(name[0])) {
  2128. ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
  2129. parse_extras,
  2130. connector,
  2131. mode);
  2132. if (ret)
  2133. return false;
  2134. mode->specified = true;
  2135. }
  2136. /* No mode? Check for freestanding extras and/or options */
  2137. if (!mode->specified) {
  2138. unsigned int len = strlen(mode_option);
  2139. if (bpp_ptr || refresh_ptr)
  2140. return false; /* syntax error */
  2141. if (len == 1 || (len >= 2 && mode_option[1] == ','))
  2142. extra_ptr = mode_option;
  2143. else
  2144. options_ptr = mode_option - 1;
  2145. freestanding = true;
  2146. }
  2147. if (bpp_ptr) {
  2148. ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
  2149. if (ret)
  2150. return false;
  2151. mode->bpp_specified = true;
  2152. }
  2153. if (refresh_ptr) {
  2154. ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
  2155. &refresh_end_ptr, mode);
  2156. if (ret)
  2157. return false;
  2158. mode->refresh_specified = true;
  2159. }
  2160. /*
  2161. * Locate the end of the bpp / refresh, and parse the extras
  2162. * if relevant
  2163. */
  2164. if (bpp_ptr && refresh_ptr)
  2165. extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
  2166. else if (bpp_ptr)
  2167. extra_ptr = bpp_end_ptr;
  2168. else if (refresh_ptr)
  2169. extra_ptr = refresh_end_ptr;
  2170. if (extra_ptr) {
  2171. if (options_ptr)
  2172. len = options_ptr - extra_ptr;
  2173. else
  2174. len = strlen(extra_ptr);
  2175. ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
  2176. connector, mode);
  2177. if (ret)
  2178. return false;
  2179. }
  2180. if (options_ptr) {
  2181. ret = drm_mode_parse_cmdline_options(options_ptr + 1,
  2182. freestanding,
  2183. connector, mode);
  2184. if (ret)
  2185. return false;
  2186. }
  2187. return true;
  2188. }
  2189. EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
  2190. static struct drm_display_mode *drm_named_mode(struct drm_device *dev,
  2191. struct drm_cmdline_mode *cmd)
  2192. {
  2193. unsigned int i;
  2194. for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
  2195. const struct drm_named_mode *named_mode = &drm_named_modes[i];
  2196. if (strcmp(cmd->name, named_mode->name))
  2197. continue;
  2198. if (!cmd->tv_mode_specified)
  2199. continue;
  2200. return drm_analog_tv_mode(dev,
  2201. named_mode->tv_mode,
  2202. named_mode->pixel_clock_khz * 1000,
  2203. named_mode->xres,
  2204. named_mode->yres,
  2205. named_mode->flags & DRM_MODE_FLAG_INTERLACE);
  2206. }
  2207. return NULL;
  2208. }
  2209. /**
  2210. * drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
  2211. * @dev: DRM device to create the new mode for
  2212. * @cmd: input command line modeline
  2213. *
  2214. * Returns:
  2215. * Pointer to converted mode on success, NULL on error.
  2216. */
  2217. struct drm_display_mode *
  2218. drm_mode_create_from_cmdline_mode(struct drm_device *dev,
  2219. struct drm_cmdline_mode *cmd)
  2220. {
  2221. struct drm_display_mode *mode;
  2222. if (cmd->xres == 0 || cmd->yres == 0)
  2223. return NULL;
  2224. if (strlen(cmd->name))
  2225. mode = drm_named_mode(dev, cmd);
  2226. else if (cmd->cvt)
  2227. mode = drm_cvt_mode(dev,
  2228. cmd->xres, cmd->yres,
  2229. cmd->refresh_specified ? cmd->refresh : 60,
  2230. cmd->rb, cmd->interlace,
  2231. cmd->margins);
  2232. else
  2233. mode = drm_gtf_mode(dev,
  2234. cmd->xres, cmd->yres,
  2235. cmd->refresh_specified ? cmd->refresh : 60,
  2236. cmd->interlace,
  2237. cmd->margins);
  2238. if (!mode)
  2239. return NULL;
  2240. mode->type |= DRM_MODE_TYPE_USERDEF;
  2241. /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
  2242. if (cmd->xres == 1366)
  2243. drm_mode_fixup_1366x768(mode);
  2244. drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
  2245. return mode;
  2246. }
  2247. EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
  2248. /**
  2249. * drm_mode_convert_to_umode - convert a drm_display_mode into a modeinfo
  2250. * @out: drm_mode_modeinfo struct to return to the user
  2251. * @in: drm_display_mode to use
  2252. *
  2253. * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
  2254. * the user.
  2255. */
  2256. void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
  2257. const struct drm_display_mode *in)
  2258. {
  2259. out->clock = in->clock;
  2260. out->hdisplay = in->hdisplay;
  2261. out->hsync_start = in->hsync_start;
  2262. out->hsync_end = in->hsync_end;
  2263. out->htotal = in->htotal;
  2264. out->hskew = in->hskew;
  2265. out->vdisplay = in->vdisplay;
  2266. out->vsync_start = in->vsync_start;
  2267. out->vsync_end = in->vsync_end;
  2268. out->vtotal = in->vtotal;
  2269. out->vscan = in->vscan;
  2270. out->vrefresh = drm_mode_vrefresh(in);
  2271. out->flags = in->flags;
  2272. out->type = in->type;
  2273. switch (in->picture_aspect_ratio) {
  2274. case HDMI_PICTURE_ASPECT_4_3:
  2275. out->flags |= DRM_MODE_FLAG_PIC_AR_4_3;
  2276. break;
  2277. case HDMI_PICTURE_ASPECT_16_9:
  2278. out->flags |= DRM_MODE_FLAG_PIC_AR_16_9;
  2279. break;
  2280. case HDMI_PICTURE_ASPECT_64_27:
  2281. out->flags |= DRM_MODE_FLAG_PIC_AR_64_27;
  2282. break;
  2283. case HDMI_PICTURE_ASPECT_256_135:
  2284. out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
  2285. break;
  2286. default:
  2287. WARN(1, "Invalid aspect ratio (0%x) on mode\n",
  2288. in->picture_aspect_ratio);
  2289. fallthrough;
  2290. case HDMI_PICTURE_ASPECT_NONE:
  2291. out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
  2292. break;
  2293. }
  2294. strscpy_pad(out->name, in->name, sizeof(out->name));
  2295. }
  2296. /**
  2297. * drm_mode_convert_umode - convert a modeinfo into a drm_display_mode
  2298. * @dev: drm device
  2299. * @out: drm_display_mode to return to the user
  2300. * @in: drm_mode_modeinfo to use
  2301. *
  2302. * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
  2303. * the caller.
  2304. *
  2305. * Returns:
  2306. * Zero on success, negative errno on failure.
  2307. */
  2308. int drm_mode_convert_umode(struct drm_device *dev,
  2309. struct drm_display_mode *out,
  2310. const struct drm_mode_modeinfo *in)
  2311. {
  2312. if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
  2313. return -ERANGE;
  2314. out->clock = in->clock;
  2315. out->hdisplay = in->hdisplay;
  2316. out->hsync_start = in->hsync_start;
  2317. out->hsync_end = in->hsync_end;
  2318. out->htotal = in->htotal;
  2319. out->hskew = in->hskew;
  2320. out->vdisplay = in->vdisplay;
  2321. out->vsync_start = in->vsync_start;
  2322. out->vsync_end = in->vsync_end;
  2323. out->vtotal = in->vtotal;
  2324. out->vscan = in->vscan;
  2325. out->flags = in->flags;
  2326. /*
  2327. * Old xf86-video-vmware (possibly others too) used to
  2328. * leave 'type' uninitialized. Just ignore any bits we
  2329. * don't like. It's a just hint after all, and more
  2330. * useful for the kernel->userspace direction anyway.
  2331. */
  2332. out->type = in->type & DRM_MODE_TYPE_ALL;
  2333. strscpy_pad(out->name, in->name, sizeof(out->name));
  2334. /* Clearing picture aspect ratio bits from out flags,
  2335. * as the aspect-ratio information is not stored in
  2336. * flags for kernel-mode, but in picture_aspect_ratio.
  2337. */
  2338. out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
  2339. switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
  2340. case DRM_MODE_FLAG_PIC_AR_4_3:
  2341. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
  2342. break;
  2343. case DRM_MODE_FLAG_PIC_AR_16_9:
  2344. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
  2345. break;
  2346. case DRM_MODE_FLAG_PIC_AR_64_27:
  2347. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27;
  2348. break;
  2349. case DRM_MODE_FLAG_PIC_AR_256_135:
  2350. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135;
  2351. break;
  2352. case DRM_MODE_FLAG_PIC_AR_NONE:
  2353. out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
  2354. break;
  2355. default:
  2356. return -EINVAL;
  2357. }
  2358. out->status = drm_mode_validate_driver(dev, out);
  2359. if (out->status != MODE_OK)
  2360. return -EINVAL;
  2361. drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
  2362. return 0;
  2363. }
  2364. /**
  2365. * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
  2366. * output format
  2367. *
  2368. * @display: display under action
  2369. * @mode: video mode to be tested.
  2370. *
  2371. * Returns:
  2372. * true if the mode can be supported in YCBCR420 format
  2373. * false if not.
  2374. */
  2375. bool drm_mode_is_420_only(const struct drm_display_info *display,
  2376. const struct drm_display_mode *mode)
  2377. {
  2378. u8 vic = drm_match_cea_mode(mode);
  2379. return test_bit(vic, display->hdmi.y420_vdb_modes);
  2380. }
  2381. EXPORT_SYMBOL(drm_mode_is_420_only);
  2382. /**
  2383. * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
  2384. * output format also (along with RGB/YCBCR444/422)
  2385. *
  2386. * @display: display under action.
  2387. * @mode: video mode to be tested.
  2388. *
  2389. * Returns:
  2390. * true if the mode can be support YCBCR420 format
  2391. * false if not.
  2392. */
  2393. bool drm_mode_is_420_also(const struct drm_display_info *display,
  2394. const struct drm_display_mode *mode)
  2395. {
  2396. u8 vic = drm_match_cea_mode(mode);
  2397. return test_bit(vic, display->hdmi.y420_cmdb_modes);
  2398. }
  2399. EXPORT_SYMBOL(drm_mode_is_420_also);
  2400. /**
  2401. * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
  2402. * output format
  2403. *
  2404. * @display: display under action.
  2405. * @mode: video mode to be tested.
  2406. *
  2407. * Returns:
  2408. * true if the mode can be supported in YCBCR420 format
  2409. * false if not.
  2410. */
  2411. bool drm_mode_is_420(const struct drm_display_info *display,
  2412. const struct drm_display_mode *mode)
  2413. {
  2414. return drm_mode_is_420_only(display, mode) ||
  2415. drm_mode_is_420_also(display, mode);
  2416. }
  2417. EXPORT_SYMBOL(drm_mode_is_420);
  2418. /**
  2419. * drm_set_preferred_mode - Sets the preferred mode of a connector
  2420. * @connector: connector whose mode list should be processed
  2421. * @hpref: horizontal resolution of preferred mode
  2422. * @vpref: vertical resolution of preferred mode
  2423. *
  2424. * Marks a mode as preferred if it matches the resolution specified by @hpref
  2425. * and @vpref.
  2426. */
  2427. void drm_set_preferred_mode(struct drm_connector *connector,
  2428. int hpref, int vpref)
  2429. {
  2430. struct drm_display_mode *mode;
  2431. list_for_each_entry(mode, &connector->probed_modes, head) {
  2432. if (mode->hdisplay == hpref &&
  2433. mode->vdisplay == vpref)
  2434. mode->type |= DRM_MODE_TYPE_PREFERRED;
  2435. }
  2436. }
  2437. EXPORT_SYMBOL(drm_set_preferred_mode);