msm_fb.c 111 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510
  1. /* drivers/video/msm/msm_fb.c
  2. *
  3. * Core MSM framebuffer driver.
  4. *
  5. * Copyright (C) 2007 Google Incorporated
  6. * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
  7. *
  8. * This software is licensed under the terms of the GNU General Public
  9. * License version 2, as published by the Free Software Foundation, and
  10. * may be copied, distributed, and modified under those terms.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/moduleparam.h>
  19. #include <linux/kernel.h>
  20. #include <linux/slab.h>
  21. #include <linux/delay.h>
  22. #include <linux/mm.h>
  23. #include <linux/fb.h>
  24. #include <linux/msm_mdp.h>
  25. #include <linux/init.h>
  26. #include <linux/ioport.h>
  27. #include <linux/device.h>
  28. #include <linux/dma-mapping.h>
  29. #include <mach/board.h>
  30. #include <linux/uaccess.h>
  31. #include <mach/iommu_domains.h>
  32. #include <linux/workqueue.h>
  33. #include <linux/string.h>
  34. #include <linux/version.h>
  35. #include <linux/proc_fs.h>
  36. #include <linux/vmalloc.h>
  37. #include <linux/debugfs.h>
  38. #include <linux/console.h>
  39. #include <linux/leds.h>
  40. #include <linux/pm_runtime.h>
  41. #include <linux/sync.h>
  42. #include <linux/sw_sync.h>
  43. #include <linux/file.h>
  44. #ifdef CONFIG_SEC_DEBUG
  45. #include <mach/sec_debug.h>
  46. #endif
  47. #define MSM_FB_C
  48. #include "msm_fb.h"
  49. #include "mddihosti.h"
  50. #include "tvenc.h"
  51. #include "mdp.h"
  52. #include "mdp4.h"
  53. #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
  54. #define MSM_FB_NUM 3
  55. #endif
  56. static unsigned char *fbram;
  57. static unsigned char *fbram_phys;
  58. static int fbram_size;
  59. static boolean bf_supported;
  60. /* Set backlight on resume after 50 ms after first
  61. * pan display on the panel. This is to avoid panel specific
  62. * transients during resume.
  63. */
  64. unsigned long backlight_duration = (HZ/20);
  65. static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
  66. static int pdev_list_cnt;
  67. int vsync_mode = 1;
  68. #define MAX_BLIT_REQ 256
  69. #define MAX_FBI_LIST 32
  70. static struct fb_info *fbi_list[MAX_FBI_LIST];
  71. static int fbi_list_index;
  72. static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST];
  73. static int mfd_list_index;
  74. static u32 msm_fb_pseudo_palette[16] = {
  75. 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
  76. 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
  77. 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
  78. 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
  79. };
  80. static struct ion_client *iclient;
  81. u32 msm_fb_debug_enabled;
  82. /* Setting msm_fb_msg_level to 8 prints out ALL messages */
  83. u32 msm_fb_msg_level = 7;
  84. /* Setting mddi_msg_level to 8 prints out ALL messages */
  85. u32 mddi_msg_level = 5;
  86. extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK];
  87. extern unsigned long mdp_timer_duration;
  88. static int msm_fb_register(struct msm_fb_data_type *mfd);
  89. static int msm_fb_open(struct fb_info *info, int user);
  90. static int msm_fb_release(struct fb_info *info, int user);
  91. static int msm_fb_pan_display(struct fb_var_screeninfo *var,
  92. struct fb_info *info);
  93. static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd);
  94. int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd);
  95. static int msm_fb_check_var(struct fb_var_screeninfo *var,
  96. struct fb_info *info);
  97. static int msm_fb_set_par(struct fb_info *info);
  98. static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
  99. boolean op_enable);
  100. static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd);
  101. static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
  102. unsigned long arg);
  103. static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma);
  104. static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
  105. struct mdp_bl_scale_data *data);
  106. static void msm_fb_scale_bl(__u32 *bl_lvl);
  107. static void msm_fb_commit_wq_handler(struct work_struct *work);
  108. static int msm_fb_pan_idle(struct msm_fb_data_type *mfd);
  109. #ifdef MSM_FB_ENABLE_DBGFS
  110. #define MSM_FB_MAX_DBGFS 1024
  111. #define MAX_BACKLIGHT_BRIGHTNESS 255
  112. /* 200 ms for time out */
  113. #define WAIT_FENCE_TIMEOUT 200
  114. int msm_fb_debugfs_file_index;
  115. struct dentry *msm_fb_debugfs_root;
  116. struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS];
  117. static int bl_scale, bl_min_lvl;
  118. DEFINE_MUTEX(msm_fb_notify_update_sem);
  119. void msmfb_no_update_notify_timer_cb(unsigned long data)
  120. {
  121. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
  122. if (!mfd)
  123. pr_err("%s mfd NULL\n", __func__);
  124. complete(&mfd->msmfb_no_update_notify);
  125. }
  126. struct dentry *msm_fb_get_debugfs_root(void)
  127. {
  128. if (msm_fb_debugfs_root == NULL)
  129. msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL);
  130. return msm_fb_debugfs_root;
  131. }
  132. void msm_fb_debugfs_file_create(struct dentry *root, const char *name,
  133. u32 *var)
  134. {
  135. if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS)
  136. return;
  137. msm_fb_debugfs_file[msm_fb_debugfs_file_index++] =
  138. debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var);
  139. }
  140. #endif
  141. int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
  142. {
  143. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  144. if (!mfd->cursor_update)
  145. return -ENODEV;
  146. return mfd->cursor_update(info, cursor);
  147. }
  148. static int msm_fb_resource_initialized;
  149. #ifndef CONFIG_FB_BACKLIGHT
  150. static int lcd_backlight_registered;
  151. static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev,
  152. enum led_brightness value)
  153. {
  154. struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
  155. int bl_lvl;
  156. if (value > MAX_BACKLIGHT_BRIGHTNESS)
  157. value = MAX_BACKLIGHT_BRIGHTNESS;
  158. /* This maps android backlight level 0 to 255 into
  159. driver backlight level 0 to bl_max with rounding */
  160. bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS)
  161. /(2 * MAX_BACKLIGHT_BRIGHTNESS);
  162. if (!bl_lvl && value)
  163. bl_lvl = 1;
  164. down(&mfd->sem);
  165. msm_fb_set_backlight(mfd, bl_lvl);
  166. up(&mfd->sem);
  167. }
  168. static struct led_classdev backlight_led = {
  169. .name = "lcd-backlight",
  170. .brightness = MAX_BACKLIGHT_BRIGHTNESS,
  171. .brightness_set = msm_fb_set_bl_brightness,
  172. };
  173. #endif
  174. static struct msm_fb_platform_data *msm_fb_pdata;
  175. unsigned char hdmi_prim_display;
  176. unsigned char hdmi_prim_resolution;
  177. int msm_fb_detect_client(const char *name)
  178. {
  179. int ret = 0;
  180. u32 len;
  181. #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
  182. u32 id;
  183. #endif
  184. if (!msm_fb_pdata)
  185. return -EPERM;
  186. len = strnlen(name, PANEL_NAME_MAX_LEN);
  187. if (strnlen(msm_fb_pdata->prim_panel_name, PANEL_NAME_MAX_LEN)) {
  188. pr_err("\n name = %s, prim_display = %s",
  189. name, msm_fb_pdata->prim_panel_name);
  190. if (!strncmp((char *)msm_fb_pdata->prim_panel_name,
  191. name, len)) {
  192. if (!strncmp((char *)msm_fb_pdata->prim_panel_name,
  193. "hdmi_msm", len))
  194. hdmi_prim_display = 1;
  195. hdmi_prim_resolution =
  196. msm_fb_pdata->ext_resolution;
  197. return 0;
  198. } else {
  199. ret = -EPERM;
  200. }
  201. }
  202. if (strnlen(msm_fb_pdata->ext_panel_name, PANEL_NAME_MAX_LEN)) {
  203. pr_err("\n name = %s, ext_display = %s",
  204. name, msm_fb_pdata->ext_panel_name);
  205. if (!strncmp((char *)msm_fb_pdata->ext_panel_name, name, len))
  206. return 0;
  207. else
  208. ret = -EPERM;
  209. }
  210. if (ret)
  211. return ret;
  212. ret = -EPERM;
  213. if (msm_fb_pdata && msm_fb_pdata->detect_client) {
  214. ret = msm_fb_pdata->detect_client(name);
  215. /* if it's non mddi panel, we need to pre-scan
  216. mddi client to see if we can disable mddi host */
  217. #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
  218. if (!ret && msm_fb_pdata->mddi_prescan)
  219. id = mddi_get_client_id();
  220. #endif
  221. }
  222. return ret;
  223. }
  224. static ssize_t msm_fb_fps_level_change(struct device *dev,
  225. struct device_attribute *attr,
  226. const char *buf, size_t count)
  227. {
  228. struct fb_info *fbi = dev_get_drvdata(dev);
  229. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
  230. struct msm_fb_panel_data *pdata =
  231. (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  232. unsigned long val;
  233. int ret;
  234. ret = kstrtoul(buf, 10, &val);
  235. if (ret)
  236. return ret;
  237. if ((val <= 0) || (val > 100))
  238. return -EINVAL;
  239. if (pdata->fps_level_change)
  240. pdata->fps_level_change(mfd->pdev, (u32)val);
  241. return count;
  242. }
  243. static ssize_t msm_fb_msm_fb_type(struct device *dev,
  244. struct device_attribute *attr, char *buf)
  245. {
  246. ssize_t ret = 0;
  247. struct fb_info *fbi = dev_get_drvdata(dev);
  248. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
  249. struct msm_fb_panel_data *pdata =
  250. (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  251. switch (pdata->panel_info.type) {
  252. case NO_PANEL:
  253. ret = snprintf(buf, PAGE_SIZE, "no panel\n");
  254. break;
  255. case MDDI_PANEL:
  256. ret = snprintf(buf, PAGE_SIZE, "mddi panel\n");
  257. break;
  258. case EBI2_PANEL:
  259. ret = snprintf(buf, PAGE_SIZE, "ebi2 panel\n");
  260. break;
  261. case LCDC_PANEL:
  262. ret = snprintf(buf, PAGE_SIZE, "lcdc panel\n");
  263. break;
  264. case EXT_MDDI_PANEL:
  265. ret = snprintf(buf, PAGE_SIZE, "ext mddi panel\n");
  266. break;
  267. case TV_PANEL:
  268. ret = snprintf(buf, PAGE_SIZE, "tv panel\n");
  269. break;
  270. case HDMI_PANEL:
  271. ret = snprintf(buf, PAGE_SIZE, "hdmi panel\n");
  272. break;
  273. case LVDS_PANEL:
  274. ret = snprintf(buf, PAGE_SIZE, "lvds panel\n");
  275. break;
  276. case DTV_PANEL:
  277. ret = snprintf(buf, PAGE_SIZE, "dtv panel\n");
  278. break;
  279. case MIPI_VIDEO_PANEL:
  280. ret = snprintf(buf, PAGE_SIZE, "mipi dsi video panel\n");
  281. break;
  282. case MIPI_CMD_PANEL:
  283. ret = snprintf(buf, PAGE_SIZE, "mipi dsi cmd panel\n");
  284. break;
  285. case WRITEBACK_PANEL:
  286. ret = snprintf(buf, PAGE_SIZE, "writeback panel\n");
  287. break;
  288. default:
  289. ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
  290. break;
  291. }
  292. return ret;
  293. }
  294. static int pcc_r = 32768, pcc_g = 32768, pcc_b = 32768;
  295. static ssize_t mdp_get_rgb(struct device *dev,
  296. struct device_attribute *attr, char *buf)
  297. {
  298. return sprintf(buf, "%d %d %d\n", pcc_r, pcc_g, pcc_b);
  299. }
  300. /**
  301. * simple color temperature interface using polynomial color correction
  302. *
  303. * input values are r/g/b adjustments from 0-32768 representing 0 -> 1
  304. *
  305. * example adjustment @ 3500K:
  306. * 1.0000 / 0.5515 / 0.2520 = 32768 / 25828 / 17347
  307. *
  308. * reference chart:
  309. * http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html
  310. */
  311. static ssize_t mdp_set_rgb(struct device *dev,
  312. struct device_attribute *attr,
  313. const char *buf, size_t count)
  314. {
  315. uint32_t r = 0, g = 0, b = 0;
  316. struct mdp_pcc_cfg_data pcc_cfg;
  317. if (count > 19)
  318. return -EINVAL;
  319. sscanf(buf, "%d %d %d", &r, &g, &b);
  320. if (r < 0 || r > 32768)
  321. return -EINVAL;
  322. if (g < 0 || g > 32768)
  323. return -EINVAL;
  324. if (b < 0 || b > 32768)
  325. return -EINVAL;
  326. pr_info("%s: r=%d g=%d b=%d", __func__, r, g, b);
  327. memset(&pcc_cfg, 0, sizeof(struct mdp_pcc_cfg_data));
  328. pcc_cfg.block = MDP_BLOCK_DMA_P;
  329. pcc_cfg.ops = MDP_PP_OPS_ENABLE | MDP_PP_OPS_WRITE;
  330. pcc_cfg.r.r = r;
  331. pcc_cfg.g.g = g;
  332. pcc_cfg.b.b = b;
  333. if (mdp4_pcc_cfg(&pcc_cfg) == 0) {
  334. pcc_r = r;
  335. pcc_g = g;
  336. pcc_b = b;
  337. return count;
  338. }
  339. return -EINVAL;
  340. }
  341. void mdp_restore_rgb(void)
  342. {
  343. struct mdp_pcc_cfg_data pcc_cfg;
  344. memset(&pcc_cfg, 0, sizeof(struct mdp_pcc_cfg_data));
  345. pcc_cfg.block = MDP_BLOCK_DMA_P;
  346. pcc_cfg.ops = MDP_PP_OPS_ENABLE | MDP_PP_OPS_WRITE;
  347. pcc_cfg.r.r = pcc_r;
  348. pcc_cfg.g.g = pcc_g;
  349. pcc_cfg.b.b = pcc_b;
  350. mdp4_pcc_cfg(&pcc_cfg);
  351. }
  352. static DEVICE_ATTR(msm_fb_type, S_IRUGO, msm_fb_msm_fb_type, NULL);
  353. static DEVICE_ATTR(msm_fb_fps_level, S_IRUGO | S_IWUGO, NULL, \
  354. msm_fb_fps_level_change);
  355. static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR | S_IWGRP, mdp_get_rgb, \
  356. mdp_set_rgb);
  357. static struct attribute *msm_fb_attrs[] = {
  358. &dev_attr_msm_fb_type.attr,
  359. &dev_attr_msm_fb_fps_level.attr,
  360. &dev_attr_rgb.attr,
  361. NULL,
  362. };
  363. static struct attribute_group msm_fb_attr_group = {
  364. .attrs = msm_fb_attrs,
  365. };
  366. static int msm_fb_create_sysfs(struct platform_device *pdev)
  367. {
  368. int rc;
  369. struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
  370. rc = sysfs_create_group(&mfd->fbi->dev->kobj, &msm_fb_attr_group);
  371. if (rc)
  372. MSM_FB_ERR("%s: sysfs group creation failed, rc=%d\n", __func__,
  373. rc);
  374. return rc;
  375. }
  376. static void msm_fb_remove_sysfs(struct platform_device *pdev)
  377. {
  378. struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
  379. sysfs_remove_group(&mfd->fbi->dev->kobj, &msm_fb_attr_group);
  380. }
  381. static void bl_workqueue_handler(struct work_struct *work);
  382. static int msm_fb_probe(struct platform_device *pdev)
  383. {
  384. struct msm_fb_data_type *mfd;
  385. int rc;
  386. int err = 0;
  387. MSM_FB_DEBUG("msm_fb_probe\n");
  388. if ((pdev->id == 0) && (pdev->num_resources > 0)) {
  389. msm_fb_pdata = pdev->dev.platform_data;
  390. fbram_size =
  391. pdev->resource[0].end - pdev->resource[0].start + 1;
  392. fbram_phys = (char *)pdev->resource[0].start;
  393. fbram = __va(fbram_phys);
  394. if (!fbram) {
  395. printk(KERN_ERR "fbram ioremap failed!\n");
  396. return -ENOMEM;
  397. }
  398. MSM_FB_DEBUG("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n",
  399. (int)fbram_phys, (int)fbram);
  400. iclient = msm_ion_client_create(-1, pdev->name);
  401. if (IS_ERR_OR_NULL(iclient)) {
  402. pr_err("msm_ion_client_create() return"
  403. " error, val %pK\n", iclient);
  404. iclient = NULL;
  405. }
  406. msm_fb_resource_initialized = 1;
  407. return 0;
  408. }
  409. if (!msm_fb_resource_initialized)
  410. return -EPERM;
  411. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  412. INIT_DELAYED_WORK(&mfd->backlight_worker, bl_workqueue_handler);
  413. if (!mfd)
  414. return -ENODEV;
  415. if (mfd->key != MFD_KEY)
  416. return -EINVAL;
  417. if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
  418. return -ENOMEM;
  419. vsync_cntrl.dev = mfd->fbi->dev;
  420. mfd->panel_info.frame_count = 0;
  421. mfd->bl_level = 0;
  422. bl_scale = 1024;
  423. bl_min_lvl = 255;
  424. #ifdef CONFIG_FB_MSM_OVERLAY
  425. mfd->overlay_play_enable = 1;
  426. #endif
  427. bf_supported = mdp4_overlay_borderfill_supported();
  428. rc = msm_fb_register(mfd);
  429. if (rc)
  430. return rc;
  431. err = pm_runtime_set_active(mfd->fbi->dev);
  432. if (err < 0)
  433. printk(KERN_ERR "pm_runtime: fail to set active.\n");
  434. pm_runtime_enable(mfd->fbi->dev);
  435. #ifdef CONFIG_FB_BACKLIGHT
  436. msm_fb_config_backlight(mfd);
  437. #else
  438. /* android supports only one lcd-backlight/lcd for now */
  439. if (!lcd_backlight_registered) {
  440. if (led_classdev_register(&pdev->dev, &backlight_led))
  441. printk(KERN_ERR "led_classdev_register failed\n");
  442. else
  443. lcd_backlight_registered = 1;
  444. }
  445. #endif
  446. pdev_list[pdev_list_cnt++] = pdev;
  447. msm_fb_create_sysfs(pdev);
  448. if (mfd->timeline == NULL) {
  449. mfd->timeline = sw_sync_timeline_create("mdp-timeline");
  450. if (mfd->timeline == NULL) {
  451. pr_err("%s: cannot create time line", __func__);
  452. return -ENOMEM;
  453. } else {
  454. mfd->timeline_value = 0;
  455. }
  456. }
  457. return 0;
  458. }
  459. static int msm_fb_remove(struct platform_device *pdev)
  460. {
  461. struct msm_fb_data_type *mfd;
  462. MSM_FB_DEBUG("msm_fb_remove\n");
  463. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  464. msm_fb_remove_sysfs(pdev);
  465. pm_runtime_disable(mfd->fbi->dev);
  466. if (!mfd)
  467. return -ENODEV;
  468. if (mfd->key != MFD_KEY)
  469. return -EINVAL;
  470. if (msm_fb_suspend_sub(mfd))
  471. printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index);
  472. if (mfd->channel_irq != 0)
  473. free_irq(mfd->channel_irq, (void *)mfd);
  474. if (mfd->vsync_width_boundary)
  475. vfree(mfd->vsync_width_boundary);
  476. if (mfd->vsync_resync_timer.function)
  477. del_timer(&mfd->vsync_resync_timer);
  478. if (mfd->refresh_timer.function)
  479. del_timer(&mfd->refresh_timer);
  480. if (mfd->dma_hrtimer.function)
  481. hrtimer_cancel(&mfd->dma_hrtimer);
  482. if (mfd->msmfb_no_update_notify_timer.function)
  483. del_timer(&mfd->msmfb_no_update_notify_timer);
  484. complete(&mfd->msmfb_no_update_notify);
  485. complete(&mfd->msmfb_update_notify);
  486. /* remove /dev/fb* */
  487. unregister_framebuffer(mfd->fbi);
  488. #ifdef CONFIG_FB_BACKLIGHT
  489. /* remove /sys/class/backlight */
  490. backlight_device_unregister(mfd->fbi->bl_dev);
  491. #else
  492. if (lcd_backlight_registered) {
  493. lcd_backlight_registered = 0;
  494. led_classdev_unregister(&backlight_led);
  495. }
  496. #endif
  497. #ifdef MSM_FB_ENABLE_DBGFS
  498. if (mfd->sub_dir)
  499. debugfs_remove(mfd->sub_dir);
  500. #endif
  501. return 0;
  502. }
  503. #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
  504. static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state)
  505. {
  506. struct msm_fb_data_type *mfd;
  507. int ret = 0;
  508. MSM_FB_DEBUG("msm_fb_suspend\n");
  509. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  510. if ((!mfd) || (mfd->key != MFD_KEY))
  511. return 0;
  512. console_lock();
  513. fb_set_suspend(mfd->fbi, FBINFO_STATE_SUSPENDED);
  514. ret = msm_fb_suspend_sub(mfd);
  515. if (ret != 0) {
  516. printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret);
  517. fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
  518. } else {
  519. pdev->dev.power.power_state = state;
  520. }
  521. console_unlock();
  522. return ret;
  523. }
  524. #else
  525. #define msm_fb_suspend NULL
  526. #endif
  527. static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd)
  528. {
  529. int ret = 0;
  530. if ((!mfd) || (mfd->key != MFD_KEY))
  531. return 0;
  532. if (mfd->msmfb_no_update_notify_timer.function)
  533. del_timer(&mfd->msmfb_no_update_notify_timer);
  534. complete(&mfd->msmfb_no_update_notify);
  535. /*
  536. * suspend this channel
  537. */
  538. mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable;
  539. mfd->suspend.op_enable = mfd->op_enable;
  540. mfd->suspend.panel_power_on = mfd->panel_power_on;
  541. mfd->suspend.op_suspend = true;
  542. if (mfd->op_enable) {
  543. ret =
  544. msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi,
  545. mfd->suspend.op_enable);
  546. if (ret) {
  547. MSM_FB_INFO
  548. ("msm_fb_suspend: can't turn off display!\n");
  549. return ret;
  550. }
  551. mfd->op_enable = FALSE;
  552. }
  553. /*
  554. * try to power down
  555. */
  556. mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  557. /*
  558. * detach display channel irq if there's any
  559. * or wait until vsync-resync completes
  560. */
  561. if ((mfd->dest == DISPLAY_LCD)) {
  562. if (mfd->panel_info.lcd.vsync_enable) {
  563. if (mfd->panel_info.lcd.hw_vsync_mode) {
  564. if (mfd->channel_irq != 0)
  565. disable_irq(mfd->channel_irq);
  566. } else {
  567. volatile boolean vh_pending;
  568. do {
  569. vh_pending = mfd->vsync_handler_pending;
  570. } while (vh_pending);
  571. }
  572. }
  573. }
  574. return 0;
  575. }
  576. #ifdef CONFIG_PM
  577. static int msm_fb_resume_sub(struct msm_fb_data_type *mfd)
  578. {
  579. int ret = 0;
  580. struct msm_fb_panel_data *pdata = NULL;
  581. if ((!mfd) || (mfd->key != MFD_KEY))
  582. return 0;
  583. pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  584. /* attach display channel irq if there's any */
  585. if (mfd->channel_irq != 0)
  586. enable_irq(mfd->channel_irq);
  587. /* resume state var recover */
  588. mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable;
  589. mfd->op_enable = mfd->suspend.op_enable;
  590. if (mfd->suspend.panel_power_on) {
  591. ret =
  592. msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi,
  593. mfd->op_enable);
  594. if (ret)
  595. MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
  596. }
  597. mfd->suspend.op_suspend = false;
  598. return ret;
  599. }
  600. #endif
  601. #if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND)
  602. static int msm_fb_resume(struct platform_device *pdev)
  603. {
  604. /* This resume function is called when interrupt is enabled.
  605. */
  606. int ret = 0;
  607. struct msm_fb_data_type *mfd;
  608. MSM_FB_DEBUG("msm_fb_resume\n");
  609. mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
  610. if ((!mfd) || (mfd->key != MFD_KEY))
  611. return 0;
  612. console_lock();
  613. ret = msm_fb_resume_sub(mfd);
  614. pdev->dev.power.power_state = PMSG_ON;
  615. fb_set_suspend(mfd->fbi, FBINFO_STATE_RUNNING);
  616. console_unlock();
  617. return ret;
  618. }
  619. #else
  620. #define msm_fb_resume NULL
  621. #endif
  622. static int msm_fb_runtime_suspend(struct device *dev)
  623. {
  624. dev_dbg(dev, "pm_runtime: suspending...\n");
  625. return 0;
  626. }
  627. static int msm_fb_runtime_resume(struct device *dev)
  628. {
  629. dev_dbg(dev, "pm_runtime: resuming...\n");
  630. return 0;
  631. }
  632. static int msm_fb_runtime_idle(struct device *dev)
  633. {
  634. dev_dbg(dev, "pm_runtime: idling...\n");
  635. return 0;
  636. }
  637. #if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
  638. static int msm_fb_ext_suspend(struct device *dev)
  639. {
  640. struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
  641. struct msm_fb_panel_data *pdata = NULL;
  642. int ret = 0;
  643. if ((!mfd) || (mfd->key != MFD_KEY))
  644. return 0;
  645. pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  646. if (mfd->panel_info.type == HDMI_PANEL ||
  647. mfd->panel_info.type == DTV_PANEL) {
  648. ret = msm_fb_suspend_sub(mfd);
  649. /* Turn off the HPD circuitry */
  650. if (pdata->power_ctrl) {
  651. MSM_FB_INFO("%s: Turning off HPD circuitry\n",
  652. __func__);
  653. pdata->power_ctrl(FALSE);
  654. }
  655. }
  656. return ret;
  657. }
  658. static int msm_fb_ext_resume(struct device *dev)
  659. {
  660. struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
  661. struct msm_fb_panel_data *pdata = NULL;
  662. int ret = 0;
  663. if ((!mfd) || (mfd->key != MFD_KEY))
  664. return 0;
  665. pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  666. if (mfd->panel_info.type == HDMI_PANEL ||
  667. mfd->panel_info.type == DTV_PANEL) {
  668. /* Turn on the HPD circuitry */
  669. if (pdata->power_ctrl) {
  670. pdata->power_ctrl(TRUE);
  671. MSM_FB_INFO("%s: Turning on HPD circuitry\n",
  672. __func__);
  673. }
  674. ret = msm_fb_resume_sub(mfd);
  675. }
  676. return ret;
  677. }
  678. #endif
  679. static struct dev_pm_ops msm_fb_dev_pm_ops = {
  680. .runtime_suspend = msm_fb_runtime_suspend,
  681. .runtime_resume = msm_fb_runtime_resume,
  682. .runtime_idle = msm_fb_runtime_idle,
  683. #if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
  684. .suspend = msm_fb_ext_suspend,
  685. .resume = msm_fb_ext_resume,
  686. #endif
  687. };
  688. static struct platform_driver msm_fb_driver = {
  689. .probe = msm_fb_probe,
  690. .remove = msm_fb_remove,
  691. #ifndef CONFIG_HAS_EARLYSUSPEND
  692. .suspend = msm_fb_suspend,
  693. .resume = msm_fb_resume,
  694. #endif
  695. .shutdown = NULL,
  696. .driver = {
  697. /* Driver name must match the device name added in platform.c. */
  698. .name = "msm_fb",
  699. .pm = &msm_fb_dev_pm_ops,
  700. },
  701. };
  702. #ifdef CONFIG_HAS_EARLYSUSPEND
  703. static void msmfb_early_suspend(struct early_suspend *h)
  704. {
  705. struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
  706. early_suspend);
  707. msm_fb_suspend_sub(mfd);
  708. }
  709. static void msmfb_early_resume(struct early_suspend *h)
  710. {
  711. struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
  712. early_suspend);
  713. msm_fb_resume_sub(mfd);
  714. }
  715. #endif
  716. static int unset_bl_level, bl_updated;
  717. static int bl_level_old;
  718. static int mdp_bl_scale_config(struct msm_fb_data_type *mfd,
  719. struct mdp_bl_scale_data *data)
  720. {
  721. int ret = 0;
  722. int curr_bl;
  723. down(&mfd->sem);
  724. curr_bl = mfd->bl_level;
  725. bl_scale = data->scale;
  726. bl_min_lvl = data->min_lvl;
  727. pr_debug("%s: update scale = %d, min_lvl = %d\n", __func__, bl_scale,
  728. bl_min_lvl);
  729. /* update current backlight to use new scaling*/
  730. msm_fb_set_backlight(mfd, curr_bl);
  731. up(&mfd->sem);
  732. return ret;
  733. }
  734. static void msm_fb_scale_bl(__u32 *bl_lvl)
  735. {
  736. __u32 temp = *bl_lvl;
  737. pr_debug("%s: input = %d, scale = %d", __func__, temp, bl_scale);
  738. if (temp >= bl_min_lvl) {
  739. /* bl_scale is the numerator of scaling fraction (x/1024)*/
  740. temp = ((*bl_lvl) * bl_scale) / 1024;
  741. /*if less than minimum level, use min level*/
  742. if (temp < bl_min_lvl)
  743. temp = bl_min_lvl;
  744. }
  745. pr_debug("%s: output = %d", __func__, temp);
  746. (*bl_lvl) = temp;
  747. }
  748. /*must call this function from within mfd->sem*/
  749. void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl)
  750. {
  751. struct msm_fb_panel_data *pdata;
  752. __u32 temp = bkl_lvl;
  753. if (!mfd->panel_power_on || !bl_updated) {
  754. unset_bl_level = bkl_lvl;
  755. return;
  756. } else {
  757. unset_bl_level = 0;
  758. }
  759. pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  760. if ((pdata) && (pdata->set_backlight)) {
  761. msm_fb_scale_bl(&temp);
  762. if (bl_level_old == temp) {
  763. return;
  764. }
  765. mfd->bl_level = temp;
  766. pdata->set_backlight(mfd);
  767. mfd->bl_level = bkl_lvl;
  768. bl_level_old = temp;
  769. }
  770. }
  771. static int msm_fb_blank_sub(int blank_mode, struct fb_info *info,
  772. boolean op_enable)
  773. {
  774. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  775. struct msm_fb_panel_data *pdata = NULL;
  776. int ret = 0;
  777. if (!op_enable)
  778. return -EPERM;
  779. pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
  780. if ((!pdata) || (!pdata->on) || (!pdata->off)) {
  781. printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n");
  782. return -ENODEV;
  783. }
  784. switch (blank_mode) {
  785. case FB_BLANK_UNBLANK:
  786. if (!mfd->panel_power_on) {
  787. msleep(16);
  788. ret = pdata->on(mfd->pdev);
  789. if (ret == 0) {
  790. mfd->panel_power_on = TRUE;
  791. /* ToDo: possible conflict with android which doesn't expect sw refresher */
  792. /*
  793. if (!mfd->hw_refresh)
  794. {
  795. if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0)
  796. {
  797. MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret);
  798. }
  799. }
  800. */
  801. }
  802. }
  803. break;
  804. case FB_BLANK_VSYNC_SUSPEND:
  805. case FB_BLANK_HSYNC_SUSPEND:
  806. case FB_BLANK_NORMAL:
  807. case FB_BLANK_POWERDOWN:
  808. default:
  809. if (mfd->panel_power_on) {
  810. int curr_pwr_state;
  811. mfd->op_enable = FALSE;
  812. curr_pwr_state = mfd->panel_power_on;
  813. mfd->panel_power_on = FALSE;
  814. cancel_delayed_work_sync(&mfd->backlight_worker);
  815. bl_updated = 0;
  816. msleep(16);
  817. ret = pdata->off(mfd->pdev);
  818. if (ret)
  819. mfd->panel_power_on = curr_pwr_state;
  820. if (mfd->timeline) {
  821. /* Adding 1 is enough when pan_display is still
  822. * a blocking call and with mutex protection.
  823. * But if it is an async call, we will still
  824. * need to add 2. Adding 2 can be safer in
  825. * order to signal all existing fences, and it
  826. * is harmless. */
  827. sw_sync_timeline_inc(mfd->timeline, 2);
  828. mfd->timeline_value += 2;
  829. }
  830. mfd->op_enable = TRUE;
  831. }
  832. break;
  833. }
  834. return ret;
  835. }
  836. int calc_fb_offset(struct msm_fb_data_type *mfd, struct fb_info *fbi, int bpp)
  837. {
  838. struct msm_panel_info *panel_info = &mfd->panel_info;
  839. int remainder, yres, offset;
  840. if (panel_info->mode2_yres != 0) {
  841. yres = panel_info->mode2_yres;
  842. remainder = (fbi->fix.line_length*yres) & (PAGE_SIZE - 1);
  843. } else {
  844. yres = panel_info->yres;
  845. remainder = (fbi->fix.line_length*yres) & (PAGE_SIZE - 1);
  846. }
  847. if (!remainder)
  848. remainder = PAGE_SIZE;
  849. if (fbi->var.yoffset < yres) {
  850. offset = (fbi->var.xoffset * bpp);
  851. /* iBuf->buf += fbi->var.xoffset * bpp + 0 *
  852. yres * fbi->fix.line_length; */
  853. } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
  854. offset = (fbi->var.xoffset * bpp + yres *
  855. fbi->fix.line_length + PAGE_SIZE - remainder);
  856. } else {
  857. offset = (fbi->var.xoffset * bpp + 2 * yres *
  858. fbi->fix.line_length + 2 * (PAGE_SIZE - remainder));
  859. }
  860. return offset;
  861. }
  862. static void msm_fb_fillrect(struct fb_info *info,
  863. const struct fb_fillrect *rect)
  864. {
  865. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  866. msm_fb_pan_idle(mfd);
  867. cfb_fillrect(info, rect);
  868. if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
  869. !mfd->sw_currently_refreshing) {
  870. struct fb_var_screeninfo var;
  871. var = info->var;
  872. var.reserved[0] = 0x54445055;
  873. var.reserved[1] = (rect->dy << 16) | (rect->dx);
  874. var.reserved[2] = ((rect->dy + rect->height) << 16) |
  875. (rect->dx + rect->width);
  876. msm_fb_pan_display(&var, info);
  877. }
  878. }
  879. static void msm_fb_copyarea(struct fb_info *info,
  880. const struct fb_copyarea *area)
  881. {
  882. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  883. msm_fb_pan_idle(mfd);
  884. cfb_copyarea(info, area);
  885. if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
  886. !mfd->sw_currently_refreshing) {
  887. struct fb_var_screeninfo var;
  888. var = info->var;
  889. var.reserved[0] = 0x54445055;
  890. var.reserved[1] = (area->dy << 16) | (area->dx);
  891. var.reserved[2] = ((area->dy + area->height) << 16) |
  892. (area->dx + area->width);
  893. msm_fb_pan_display(&var, info);
  894. }
  895. }
  896. static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image)
  897. {
  898. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  899. msm_fb_pan_idle(mfd);
  900. cfb_imageblit(info, image);
  901. if (!mfd->hw_refresh && (info->var.yoffset == 0) &&
  902. !mfd->sw_currently_refreshing) {
  903. struct fb_var_screeninfo var;
  904. var = info->var;
  905. var.reserved[0] = 0x54445055;
  906. var.reserved[1] = (image->dy << 16) | (image->dx);
  907. var.reserved[2] = ((image->dy + image->height) << 16) |
  908. (image->dx + image->width);
  909. msm_fb_pan_display(&var, info);
  910. }
  911. }
  912. static int msm_fb_blank(int blank_mode, struct fb_info *info)
  913. {
  914. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  915. msm_fb_pan_idle(mfd);
  916. return msm_fb_blank_sub(blank_mode, info, mfd->op_enable);
  917. }
  918. static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info)
  919. {
  920. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  921. if (!mfd->lut_update)
  922. return -ENODEV;
  923. mfd->lut_update(info, cmap);
  924. return 0;
  925. }
  926. /*
  927. * Custom Framebuffer mmap() function for MSM driver.
  928. * Differs from standard mmap() function by allowing for customized
  929. * page-protection.
  930. */
  931. static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma)
  932. {
  933. /* Get frame buffer memory range. */
  934. unsigned long start = info->fix.smem_start;
  935. u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
  936. unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
  937. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  938. msm_fb_pan_idle(mfd);
  939. if (off >= len) {
  940. /* memory mapped io */
  941. off -= len;
  942. if (info->var.accel_flags) {
  943. mutex_unlock(&info->lock);
  944. return -EINVAL;
  945. }
  946. start = info->fix.mmio_start;
  947. len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
  948. }
  949. /* Set VM flags. */
  950. start &= PAGE_MASK;
  951. if ((vma->vm_end - vma->vm_start + off) > len)
  952. return -EINVAL;
  953. off += start;
  954. vma->vm_pgoff = off >> PAGE_SHIFT;
  955. /* This is an IO map - tell maydump to skip this VMA */
  956. vma->vm_flags |= VM_IO | VM_RESERVED;
  957. /* Set VM page protection */
  958. if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE)
  959. vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
  960. else if (mfd->mdp_fb_page_protection ==
  961. MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE)
  962. vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot);
  963. else if (mfd->mdp_fb_page_protection ==
  964. MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE)
  965. vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot);
  966. else if (mfd->mdp_fb_page_protection ==
  967. MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE)
  968. vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot);
  969. else
  970. vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  971. /* Remap the frame buffer I/O range */
  972. if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
  973. vma->vm_end - vma->vm_start,
  974. vma->vm_page_prot))
  975. return -EAGAIN;
  976. return 0;
  977. }
  978. static struct fb_ops msm_fb_ops = {
  979. .owner = THIS_MODULE,
  980. .fb_open = msm_fb_open,
  981. .fb_release = msm_fb_release,
  982. .fb_read = NULL,
  983. .fb_write = NULL,
  984. .fb_cursor = NULL,
  985. .fb_check_var = msm_fb_check_var, /* vinfo check */
  986. .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */
  987. .fb_setcolreg = NULL, /* set color register */
  988. .fb_blank = msm_fb_blank, /* blank display */
  989. .fb_pan_display = msm_fb_pan_display, /* pan display */
  990. .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */
  991. .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */
  992. .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */
  993. .fb_rotate = NULL,
  994. .fb_sync = NULL, /* wait for blit idle, optional */
  995. .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */
  996. .fb_mmap = msm_fb_mmap,
  997. };
  998. static __u32 msm_fb_line_length(__u32 fb_index, __u32 xres, int bpp)
  999. {
  1000. /* The adreno GPU hardware requires that the pitch be aligned to
  1001. 32 pixels for color buffers, so for the cases where the GPU
  1002. is writing directly to fb0, the framebuffer pitch
  1003. also needs to be 32 pixel aligned */
  1004. if (fb_index == 0)
  1005. return ALIGN(xres, 32) * bpp;
  1006. else
  1007. return xres * bpp;
  1008. }
  1009. static int msm_fb_register(struct msm_fb_data_type *mfd)
  1010. {
  1011. int ret = -ENODEV;
  1012. int bpp;
  1013. struct msm_panel_info *panel_info = &mfd->panel_info;
  1014. struct fb_info *fbi = mfd->fbi;
  1015. struct fb_fix_screeninfo *fix;
  1016. struct fb_var_screeninfo *var;
  1017. int *id;
  1018. int fbram_offset;
  1019. int remainder, remainder_mode2;
  1020. /*
  1021. * fb info initialization
  1022. */
  1023. fix = &fbi->fix;
  1024. var = &fbi->var;
  1025. fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */
  1026. fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */
  1027. fix->ywrapstep = 0; /* No support */
  1028. fix->mmio_start = 0; /* No MMIO Address */
  1029. fix->mmio_len = 0; /* No MMIO Address */
  1030. fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */
  1031. var->xoffset = 0, /* Offset from virtual to visible */
  1032. var->yoffset = 0, /* resolution */
  1033. var->grayscale = 0, /* No graylevels */
  1034. var->nonstd = 0, /* standard pixel format */
  1035. var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */
  1036. var->height = -1, /* height of picture in mm */
  1037. var->width = -1, /* width of picture in mm */
  1038. var->accel_flags = 0, /* acceleration flags */
  1039. var->sync = 0, /* see FB_SYNC_* */
  1040. var->rotate = 0, /* angle we rotate counter clockwise */
  1041. mfd->op_enable = FALSE;
  1042. switch (mfd->fb_imgType) {
  1043. case MDP_RGB_565:
  1044. fix->type = FB_TYPE_PACKED_PIXELS;
  1045. fix->xpanstep = 1;
  1046. fix->ypanstep = 1;
  1047. var->vmode = FB_VMODE_NONINTERLACED;
  1048. var->blue.offset = 0;
  1049. var->green.offset = 5;
  1050. var->red.offset = 11;
  1051. var->blue.length = 5;
  1052. var->green.length = 6;
  1053. var->red.length = 5;
  1054. var->blue.msb_right = 0;
  1055. var->green.msb_right = 0;
  1056. var->red.msb_right = 0;
  1057. var->transp.offset = 0;
  1058. var->transp.length = 0;
  1059. bpp = 2;
  1060. break;
  1061. case MDP_RGB_888:
  1062. fix->type = FB_TYPE_PACKED_PIXELS;
  1063. fix->xpanstep = 1;
  1064. fix->ypanstep = 1;
  1065. var->vmode = FB_VMODE_NONINTERLACED;
  1066. var->blue.offset = 0;
  1067. var->green.offset = 8;
  1068. var->red.offset = 16;
  1069. var->blue.length = 8;
  1070. var->green.length = 8;
  1071. var->red.length = 8;
  1072. var->blue.msb_right = 0;
  1073. var->green.msb_right = 0;
  1074. var->red.msb_right = 0;
  1075. var->transp.offset = 0;
  1076. var->transp.length = 0;
  1077. bpp = 3;
  1078. break;
  1079. case MDP_ARGB_8888:
  1080. fix->type = FB_TYPE_PACKED_PIXELS;
  1081. fix->xpanstep = 1;
  1082. fix->ypanstep = 1;
  1083. var->vmode = FB_VMODE_NONINTERLACED;
  1084. var->blue.offset = 0;
  1085. var->green.offset = 8;
  1086. var->red.offset = 16;
  1087. var->blue.length = 8;
  1088. var->green.length = 8;
  1089. var->red.length = 8;
  1090. var->blue.msb_right = 0;
  1091. var->green.msb_right = 0;
  1092. var->red.msb_right = 0;
  1093. var->transp.offset = 24;
  1094. var->transp.length = 8;
  1095. bpp = 4;
  1096. break;
  1097. case MDP_RGBA_8888:
  1098. fix->type = FB_TYPE_PACKED_PIXELS;
  1099. fix->xpanstep = 1;
  1100. fix->ypanstep = 1;
  1101. var->vmode = FB_VMODE_NONINTERLACED;
  1102. var->blue.offset = 8;
  1103. var->green.offset = 16;
  1104. var->red.offset = 24;
  1105. var->blue.length = 8;
  1106. var->green.length = 8;
  1107. var->red.length = 8;
  1108. var->blue.msb_right = 0;
  1109. var->green.msb_right = 0;
  1110. var->red.msb_right = 0;
  1111. var->transp.offset = 0;
  1112. var->transp.length = 8;
  1113. bpp = 4;
  1114. break;
  1115. case MDP_BGRA_8888:
  1116. fix->type = FB_TYPE_PACKED_PIXELS;
  1117. fix->xpanstep = 1;
  1118. fix->ypanstep = 1;
  1119. var->vmode = FB_VMODE_NONINTERLACED;
  1120. var->blue.offset = 0;
  1121. var->green.offset = 8;
  1122. var->red.offset = 16;
  1123. var->blue.length = 8;
  1124. var->green.length = 8;
  1125. var->red.length = 8;
  1126. var->blue.msb_right = 0;
  1127. var->green.msb_right = 0;
  1128. var->red.msb_right = 0;
  1129. var->transp.offset = 24;
  1130. var->transp.length = 8;
  1131. bpp = 4;
  1132. break;
  1133. case MDP_YCRYCB_H2V1:
  1134. /* ToDo: need to check TV-Out YUV422i framebuffer format */
  1135. /* we might need to create new type define */
  1136. fix->type = FB_TYPE_INTERLEAVED_PLANES;
  1137. fix->xpanstep = 2;
  1138. fix->ypanstep = 1;
  1139. var->vmode = FB_VMODE_NONINTERLACED;
  1140. /* how about R/G/B offset? */
  1141. var->blue.offset = 0;
  1142. var->green.offset = 5;
  1143. var->red.offset = 11;
  1144. var->blue.length = 5;
  1145. var->green.length = 6;
  1146. var->red.length = 5;
  1147. var->blue.msb_right = 0;
  1148. var->green.msb_right = 0;
  1149. var->red.msb_right = 0;
  1150. var->transp.offset = 0;
  1151. var->transp.length = 0;
  1152. bpp = 2;
  1153. break;
  1154. default:
  1155. MSM_FB_ERR("msm_fb_init: fb %d unkown image type!\n",
  1156. mfd->index);
  1157. return ret;
  1158. }
  1159. fix->type = panel_info->is_3d_panel;
  1160. fix->line_length = msm_fb_line_length(mfd->index, panel_info->xres,
  1161. bpp);
  1162. /* Make sure all buffers can be addressed on a page boundary by an x
  1163. * and y offset */
  1164. remainder = (fix->line_length * panel_info->yres) & (PAGE_SIZE - 1);
  1165. /* PAGE_SIZE is a power of 2 */
  1166. if (!remainder)
  1167. remainder = PAGE_SIZE;
  1168. remainder_mode2 = (fix->line_length *
  1169. panel_info->mode2_yres) & (PAGE_SIZE - 1);
  1170. if (!remainder_mode2)
  1171. remainder_mode2 = PAGE_SIZE;
  1172. /*
  1173. * calculate smem_len based on max size of two supplied modes.
  1174. * Only fb0 has mem. fb1 and fb2 don't have mem.
  1175. */
  1176. if (!bf_supported || mfd->index == 0)
  1177. fix->smem_len = MAX((msm_fb_line_length(mfd->index,
  1178. panel_info->xres,
  1179. bpp) *
  1180. panel_info->yres + PAGE_SIZE -
  1181. remainder) * mfd->fb_page,
  1182. (msm_fb_line_length(mfd->index,
  1183. panel_info->mode2_xres,
  1184. bpp) *
  1185. panel_info->mode2_yres + PAGE_SIZE -
  1186. remainder_mode2) * mfd->fb_page);
  1187. else if (mfd->index == 1 || mfd->index == 2) {
  1188. pr_debug("%s:%d no memory is allocated for fb%d!\n",
  1189. __func__, __LINE__, mfd->index);
  1190. fix->smem_len = 0;
  1191. }
  1192. mfd->var_xres = panel_info->xres;
  1193. mfd->var_yres = panel_info->yres;
  1194. mfd->var_frame_rate = panel_info->frame_rate;
  1195. var->pixclock = mfd->panel_info.clk_rate;
  1196. mfd->var_pixclock = var->pixclock;
  1197. var->xres = panel_info->xres;
  1198. var->yres = panel_info->yres;
  1199. var->xres_virtual = panel_info->xres;
  1200. var->yres_virtual = panel_info->yres * mfd->fb_page +
  1201. ((PAGE_SIZE - remainder)/fix->line_length) * mfd->fb_page;
  1202. var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */
  1203. /*
  1204. * id field for fb app
  1205. */
  1206. id = (int *)&mfd->panel;
  1207. switch (mdp_rev) {
  1208. case MDP_REV_20:
  1209. snprintf(fix->id, sizeof(fix->id), "msmfb20_%x", (__u32) *id);
  1210. break;
  1211. case MDP_REV_22:
  1212. snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id);
  1213. break;
  1214. case MDP_REV_30:
  1215. snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id);
  1216. break;
  1217. case MDP_REV_303:
  1218. snprintf(fix->id, sizeof(fix->id), "msmfb303_%x", (__u32) *id);
  1219. break;
  1220. case MDP_REV_31:
  1221. snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
  1222. break;
  1223. case MDP_REV_40:
  1224. snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
  1225. break;
  1226. case MDP_REV_41:
  1227. snprintf(fix->id, sizeof(fix->id), "msmfb41_%x", (__u32) *id);
  1228. break;
  1229. case MDP_REV_42:
  1230. snprintf(fix->id, sizeof(fix->id), "msmfb42_%x", (__u32) *id);
  1231. break;
  1232. case MDP_REV_43:
  1233. snprintf(fix->id, sizeof(fix->id), "msmfb43_%x", (__u32) *id);
  1234. break;
  1235. case MDP_REV_44:
  1236. snprintf(fix->id, sizeof(fix->id), "msmfb44_%x", (__u32) *id);
  1237. break;
  1238. default:
  1239. snprintf(fix->id, sizeof(fix->id), "msmfb0_%x", (__u32) *id);
  1240. break;
  1241. }
  1242. fbi->fbops = &msm_fb_ops;
  1243. fbi->flags = FBINFO_FLAG_DEFAULT;
  1244. fbi->pseudo_palette = msm_fb_pseudo_palette;
  1245. mfd->ref_cnt = 0;
  1246. mfd->sw_currently_refreshing = FALSE;
  1247. mfd->sw_refreshing_enable = TRUE;
  1248. mfd->panel_power_on = FALSE;
  1249. mfd->pan_waiting = FALSE;
  1250. init_completion(&mfd->pan_comp);
  1251. init_completion(&mfd->refresher_comp);
  1252. sema_init(&mfd->sem, 1);
  1253. init_timer(&mfd->msmfb_no_update_notify_timer);
  1254. mfd->msmfb_no_update_notify_timer.function =
  1255. msmfb_no_update_notify_timer_cb;
  1256. mfd->msmfb_no_update_notify_timer.data = (unsigned long)mfd;
  1257. init_completion(&mfd->msmfb_update_notify);
  1258. init_completion(&mfd->msmfb_no_update_notify);
  1259. init_completion(&mfd->commit_comp);
  1260. mutex_init(&mfd->sync_mutex);
  1261. INIT_WORK(&mfd->commit_work, msm_fb_commit_wq_handler);
  1262. mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
  1263. GFP_KERNEL);
  1264. if (mfd->msm_fb_backup == 0) {
  1265. pr_err("error: not enough memory!\n");
  1266. return -ENOMEM;
  1267. }
  1268. fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram;
  1269. fbram += fbram_offset;
  1270. fbram_phys += fbram_offset;
  1271. fbram_size -= fbram_offset;
  1272. if (!bf_supported || mfd->index == 0)
  1273. if (fbram_size < fix->smem_len) {
  1274. pr_err("error: no more framebuffer memory!\n");
  1275. return -ENOMEM;
  1276. }
  1277. fbi->screen_base = fbram;
  1278. fbi->fix.smem_start = (unsigned long)fbram_phys;
  1279. msm_iommu_map_contig_buffer(fbi->fix.smem_start,
  1280. DISPLAY_WRITE_DOMAIN,
  1281. GEN_POOL,
  1282. fbi->fix.smem_len,
  1283. SZ_4K,
  1284. 0,
  1285. &(mfd->display_iova));
  1286. msm_iommu_map_contig_buffer(fbi->fix.smem_start,
  1287. DISPLAY_READ_DOMAIN,
  1288. GEN_POOL,
  1289. fbi->fix.smem_len,
  1290. SZ_4K,
  1291. 0,
  1292. &(mfd->display_iova));
  1293. msm_iommu_map_contig_buffer(fbi->fix.smem_start,
  1294. ROTATOR_SRC_DOMAIN,
  1295. GEN_POOL,
  1296. fbi->fix.smem_len,
  1297. SZ_4K,
  1298. 0,
  1299. &(mfd->rotator_iova));
  1300. if (!bf_supported || mfd->index == 0)
  1301. memset(fbi->screen_base, 0x0, fix->smem_len);
  1302. mfd->op_enable = TRUE;
  1303. mfd->panel_power_on = FALSE;
  1304. /* cursor memory allocation */
  1305. if (mfd->cursor_update) {
  1306. unsigned long cursor_buf_iommu = 0;
  1307. mfd->cursor_buf = dma_alloc_coherent(NULL,
  1308. MDP_CURSOR_SIZE,
  1309. (dma_addr_t *) &mfd->cursor_buf_phys,
  1310. GFP_KERNEL);
  1311. msm_iommu_map_contig_buffer((unsigned long)mfd->cursor_buf_phys,
  1312. DISPLAY_READ_DOMAIN,
  1313. GEN_POOL,
  1314. MDP_CURSOR_SIZE,
  1315. SZ_4K,
  1316. 0,
  1317. &cursor_buf_iommu);
  1318. if (cursor_buf_iommu)
  1319. mfd->cursor_buf_phys = (void *)cursor_buf_iommu;
  1320. if (!mfd->cursor_buf)
  1321. mfd->cursor_update = 0;
  1322. }
  1323. if (mfd->lut_update) {
  1324. ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
  1325. if (ret)
  1326. printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n",
  1327. __func__);
  1328. }
  1329. if (register_framebuffer(fbi) < 0) {
  1330. if (mfd->lut_update)
  1331. fb_dealloc_cmap(&fbi->cmap);
  1332. if (mfd->cursor_buf)
  1333. dma_free_coherent(NULL,
  1334. MDP_CURSOR_SIZE,
  1335. mfd->cursor_buf,
  1336. (dma_addr_t) mfd->cursor_buf_phys);
  1337. mfd->op_enable = FALSE;
  1338. return -EPERM;
  1339. }
  1340. fbram += fix->smem_len;
  1341. fbram_phys += fix->smem_len;
  1342. fbram_size -= fix->smem_len;
  1343. MSM_FB_INFO
  1344. ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n",
  1345. mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len);
  1346. #ifdef CONFIG_FB_MSM_LOGO
  1347. /* Flip buffer */
  1348. if (!load_565rle_image(INIT_IMAGE_FILE, bf_supported))
  1349. ;
  1350. #endif
  1351. ret = 0;
  1352. #ifdef CONFIG_HAS_EARLYSUSPEND
  1353. if (mfd->panel_info.type != DTV_PANEL) {
  1354. mfd->early_suspend.suspend = msmfb_early_suspend;
  1355. mfd->early_suspend.resume = msmfb_early_resume;
  1356. mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
  1357. register_early_suspend(&mfd->early_suspend);
  1358. }
  1359. #endif
  1360. #ifdef MSM_FB_ENABLE_DBGFS
  1361. {
  1362. struct dentry *root;
  1363. struct dentry *sub_dir;
  1364. char sub_name[2];
  1365. root = msm_fb_get_debugfs_root();
  1366. if (root != NULL) {
  1367. sub_name[0] = (char)(mfd->index + 0x30);
  1368. sub_name[1] = '\0';
  1369. sub_dir = debugfs_create_dir(sub_name, root);
  1370. } else {
  1371. sub_dir = NULL;
  1372. }
  1373. mfd->sub_dir = sub_dir;
  1374. if (sub_dir) {
  1375. msm_fb_debugfs_file_create(sub_dir, "op_enable",
  1376. (u32 *) &mfd->op_enable);
  1377. msm_fb_debugfs_file_create(sub_dir, "panel_power_on",
  1378. (u32 *) &mfd->
  1379. panel_power_on);
  1380. msm_fb_debugfs_file_create(sub_dir, "ref_cnt",
  1381. (u32 *) &mfd->ref_cnt);
  1382. msm_fb_debugfs_file_create(sub_dir, "fb_imgType",
  1383. (u32 *) &mfd->fb_imgType);
  1384. msm_fb_debugfs_file_create(sub_dir,
  1385. "sw_currently_refreshing",
  1386. (u32 *) &mfd->
  1387. sw_currently_refreshing);
  1388. msm_fb_debugfs_file_create(sub_dir,
  1389. "sw_refreshing_enable",
  1390. (u32 *) &mfd->
  1391. sw_refreshing_enable);
  1392. msm_fb_debugfs_file_create(sub_dir, "xres",
  1393. (u32 *) &mfd->panel_info.
  1394. xres);
  1395. msm_fb_debugfs_file_create(sub_dir, "yres",
  1396. (u32 *) &mfd->panel_info.
  1397. yres);
  1398. msm_fb_debugfs_file_create(sub_dir, "bpp",
  1399. (u32 *) &mfd->panel_info.
  1400. bpp);
  1401. msm_fb_debugfs_file_create(sub_dir, "type",
  1402. (u32 *) &mfd->panel_info.
  1403. type);
  1404. msm_fb_debugfs_file_create(sub_dir, "wait_cycle",
  1405. (u32 *) &mfd->panel_info.
  1406. wait_cycle);
  1407. msm_fb_debugfs_file_create(sub_dir, "pdest",
  1408. (u32 *) &mfd->panel_info.
  1409. pdest);
  1410. msm_fb_debugfs_file_create(sub_dir, "backbuff",
  1411. (u32 *) &mfd->panel_info.
  1412. fb_num);
  1413. msm_fb_debugfs_file_create(sub_dir, "clk_rate",
  1414. (u32 *) &mfd->panel_info.
  1415. clk_rate);
  1416. msm_fb_debugfs_file_create(sub_dir, "frame_count",
  1417. (u32 *) &mfd->panel_info.
  1418. frame_count);
  1419. switch (mfd->dest) {
  1420. case DISPLAY_LCD:
  1421. msm_fb_debugfs_file_create(sub_dir,
  1422. "vsync_enable",
  1423. (u32 *)&mfd->panel_info.lcd.vsync_enable);
  1424. msm_fb_debugfs_file_create(sub_dir,
  1425. "refx100",
  1426. (u32 *) &mfd->panel_info.lcd. refx100);
  1427. msm_fb_debugfs_file_create(sub_dir,
  1428. "v_back_porch",
  1429. (u32 *) &mfd->panel_info.lcd.v_back_porch);
  1430. msm_fb_debugfs_file_create(sub_dir,
  1431. "v_front_porch",
  1432. (u32 *) &mfd->panel_info.lcd.v_front_porch);
  1433. msm_fb_debugfs_file_create(sub_dir,
  1434. "v_pulse_width",
  1435. (u32 *) &mfd->panel_info.lcd.v_pulse_width);
  1436. msm_fb_debugfs_file_create(sub_dir,
  1437. "hw_vsync_mode",
  1438. (u32 *) &mfd->panel_info.lcd.hw_vsync_mode);
  1439. msm_fb_debugfs_file_create(sub_dir,
  1440. "vsync_notifier_period", (u32 *)
  1441. &mfd->panel_info.lcd.vsync_notifier_period);
  1442. break;
  1443. case DISPLAY_LCDC:
  1444. msm_fb_debugfs_file_create(sub_dir,
  1445. "h_back_porch",
  1446. (u32 *) &mfd->panel_info.lcdc.h_back_porch);
  1447. msm_fb_debugfs_file_create(sub_dir,
  1448. "h_front_porch",
  1449. (u32 *) &mfd->panel_info.lcdc.h_front_porch);
  1450. msm_fb_debugfs_file_create(sub_dir,
  1451. "h_pulse_width",
  1452. (u32 *) &mfd->panel_info.lcdc.h_pulse_width);
  1453. msm_fb_debugfs_file_create(sub_dir,
  1454. "v_back_porch",
  1455. (u32 *) &mfd->panel_info.lcdc.v_back_porch);
  1456. msm_fb_debugfs_file_create(sub_dir,
  1457. "v_front_porch",
  1458. (u32 *) &mfd->panel_info.lcdc.v_front_porch);
  1459. msm_fb_debugfs_file_create(sub_dir,
  1460. "v_pulse_width",
  1461. (u32 *) &mfd->panel_info.lcdc.v_pulse_width);
  1462. msm_fb_debugfs_file_create(sub_dir,
  1463. "border_clr",
  1464. (u32 *) &mfd->panel_info.lcdc.border_clr);
  1465. msm_fb_debugfs_file_create(sub_dir,
  1466. "underflow_clr",
  1467. (u32 *) &mfd->panel_info.lcdc.underflow_clr);
  1468. msm_fb_debugfs_file_create(sub_dir,
  1469. "hsync_skew",
  1470. (u32 *) &mfd->panel_info.lcdc.hsync_skew);
  1471. break;
  1472. default:
  1473. break;
  1474. }
  1475. }
  1476. }
  1477. #endif /* MSM_FB_ENABLE_DBGFS */
  1478. return ret;
  1479. }
  1480. static int msm_fb_open(struct fb_info *info, int user)
  1481. {
  1482. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  1483. bool unblank = true;
  1484. int result;
  1485. result = pm_runtime_get_sync(info->dev);
  1486. if (result < 0) {
  1487. printk(KERN_ERR "pm_runtime: fail to wake up\n");
  1488. }
  1489. if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
  1490. mfd->ref_cnt++;
  1491. return 0;
  1492. }
  1493. if (!mfd->ref_cnt) {
  1494. if (!bf_supported ||
  1495. (info->node != 1 && info->node != 2))
  1496. mdp_set_dma_pan_info(info, NULL, TRUE);
  1497. else
  1498. pr_debug("%s:%d no mdp_set_dma_pan_info %d\n",
  1499. __func__, __LINE__, info->node);
  1500. if (mfd->is_panel_ready && !mfd->is_panel_ready())
  1501. unblank = false;
  1502. if (unblank) {
  1503. if (msm_fb_blank_sub(FB_BLANK_UNBLANK,
  1504. info, mfd->op_enable)) {
  1505. MSM_FB_ERR("%s: can't turn on display!\n",
  1506. __func__);
  1507. return -EPERM;
  1508. }
  1509. }
  1510. }
  1511. mfd->ref_cnt++;
  1512. return 0;
  1513. }
  1514. static int msm_fb_release(struct fb_info *info, int user)
  1515. {
  1516. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  1517. int ret = 0;
  1518. if (!mfd->ref_cnt) {
  1519. MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n",
  1520. mfd->index);
  1521. return -EINVAL;
  1522. }
  1523. mfd->ref_cnt--;
  1524. if (!mfd->ref_cnt) {
  1525. if ((ret =
  1526. msm_fb_blank_sub(FB_BLANK_POWERDOWN, info,
  1527. mfd->op_enable)) != 0) {
  1528. printk(KERN_ERR "msm_fb_release: can't turn off display!\n");
  1529. return ret;
  1530. }
  1531. }
  1532. pm_runtime_put(info->dev);
  1533. return ret;
  1534. }
  1535. int msm_fb_wait_for_fence(struct msm_fb_data_type *mfd)
  1536. {
  1537. int i, ret = 0;
  1538. /* buf sync */
  1539. for (i = 0; i < mfd->acq_fen_cnt; i++) {
  1540. ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
  1541. sync_fence_put(mfd->acq_fen[i]);
  1542. if (ret < 0) {
  1543. pr_err("%s: sync_fence_wait failed! ret = %x\n",
  1544. __func__, ret);
  1545. break;
  1546. }
  1547. }
  1548. mfd->acq_fen_cnt = 0;
  1549. return ret;
  1550. }
  1551. int msm_fb_signal_timeline(struct msm_fb_data_type *mfd)
  1552. {
  1553. mutex_lock(&mfd->sync_mutex);
  1554. if (mfd->timeline) {
  1555. sw_sync_timeline_inc(mfd->timeline, 1);
  1556. mfd->timeline_value++;
  1557. }
  1558. mfd->last_rel_fence = mfd->cur_rel_fence;
  1559. mfd->cur_rel_fence = 0;
  1560. mutex_unlock(&mfd->sync_mutex);
  1561. return 0;
  1562. }
  1563. static void bl_workqueue_handler(struct work_struct *work)
  1564. {
  1565. struct msm_fb_data_type *mfd = container_of(to_delayed_work(work),
  1566. struct msm_fb_data_type, backlight_worker);
  1567. struct msm_fb_panel_data *pdata = mfd->pdev->dev.platform_data;
  1568. if ((pdata) && (pdata->set_backlight) && (!bl_updated)) {
  1569. down(&mfd->sem);
  1570. mfd->bl_level = unset_bl_level;
  1571. pdata->set_backlight(mfd);
  1572. bl_level_old = unset_bl_level;
  1573. bl_updated = 1;
  1574. up(&mfd->sem);
  1575. }
  1576. }
  1577. DEFINE_SEMAPHORE(msm_fb_pan_sem);
  1578. static int msm_fb_pan_idle(struct msm_fb_data_type *mfd)
  1579. {
  1580. int ret = 0;
  1581. mutex_lock(&mfd->sync_mutex);
  1582. if (mfd->is_committing) {
  1583. mutex_unlock(&mfd->sync_mutex);
  1584. ret = wait_for_completion_interruptible_timeout(
  1585. &mfd->commit_comp,
  1586. msecs_to_jiffies(WAIT_FENCE_TIMEOUT));
  1587. if (ret <= 0)
  1588. ret = -ERESTARTSYS;
  1589. else if (!ret)
  1590. pr_err("%s wait for commit_comp timeout %d %d",
  1591. __func__, ret, mfd->is_committing);
  1592. } else {
  1593. mutex_unlock(&mfd->sync_mutex);
  1594. }
  1595. return ret;
  1596. }
  1597. static int msm_fb_pan_display_ex(struct fb_var_screeninfo *var,
  1598. struct fb_info *info, u32 wait_for_finish)
  1599. {
  1600. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  1601. struct msm_fb_backup_type *fb_backup;
  1602. int ret = 0;
  1603. /*
  1604. * If framebuffer is 2, io pen display is not allowed.
  1605. */
  1606. if (bf_supported && info->node == 2) {
  1607. pr_err("%s: no pan display for fb%d!",
  1608. __func__, info->node);
  1609. return -EPERM;
  1610. }
  1611. if (info->node != 0 || mfd->cont_splash_done) /* primary */
  1612. if ((!mfd->op_enable) || (!mfd->panel_power_on))
  1613. return -EPERM;
  1614. if (var->xoffset > (info->var.xres_virtual - info->var.xres))
  1615. return -EINVAL;
  1616. if (var->yoffset > (info->var.yres_virtual - info->var.yres))
  1617. return -EINVAL;
  1618. msm_fb_pan_idle(mfd);
  1619. mutex_lock(&mfd->sync_mutex);
  1620. if (info->fix.xpanstep)
  1621. info->var.xoffset =
  1622. (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
  1623. if (info->fix.ypanstep)
  1624. info->var.yoffset =
  1625. (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
  1626. fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
  1627. memcpy(&fb_backup->info, info, sizeof(struct fb_info));
  1628. memcpy(&fb_backup->var, var, sizeof(struct fb_var_screeninfo));
  1629. mfd->is_committing = 1;
  1630. INIT_COMPLETION(mfd->commit_comp);
  1631. schedule_work(&mfd->commit_work);
  1632. mutex_unlock(&mfd->sync_mutex);
  1633. if (wait_for_finish)
  1634. msm_fb_pan_idle(mfd);
  1635. return ret;
  1636. }
  1637. static inline int rt_policy(int policy)
  1638. {
  1639. if (unlikely(policy == SCHED_FIFO) ||
  1640. unlikely(policy == SCHED_RR))
  1641. return 1;
  1642. return 0;
  1643. }
  1644. static inline int task_has_rt_policy(struct task_struct *p)
  1645. {
  1646. return rt_policy(p->policy);
  1647. }
  1648. static int msm_fb_pan_display(struct fb_var_screeninfo *var,
  1649. struct fb_info *info)
  1650. {
  1651. return msm_fb_pan_display_ex(var, info, TRUE);
  1652. }
  1653. static int msm_fb_pan_display_sub(struct fb_var_screeninfo *var,
  1654. struct fb_info *info)
  1655. {
  1656. struct sched_param s = { .sched_priority = 1 };
  1657. struct mdp_dirty_region dirty;
  1658. struct mdp_dirty_region *dirtyPtr = NULL;
  1659. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  1660. /*
  1661. * If framebuffer is 2, io pen display is not allowed.
  1662. */
  1663. if (bf_supported && info->node == 2) {
  1664. pr_err("%s: no pan display for fb%d!",
  1665. __func__, info->node);
  1666. return -EPERM;
  1667. }
  1668. if (!task_has_rt_policy(current)) {
  1669. struct cred *new = prepare_creds();
  1670. cap_raise(new->cap_effective, CAP_SYS_NICE);
  1671. commit_creds(new);
  1672. if ((sched_setscheduler(current, SCHED_RR, &s)) < 0)
  1673. pr_err("sched_setscheduler failed\n");
  1674. }
  1675. if (info->node != 0 || mfd->cont_splash_done) /* primary */
  1676. if ((!mfd->op_enable) || (!mfd->panel_power_on))
  1677. return -EPERM;
  1678. if (var->xoffset > (info->var.xres_virtual - info->var.xres))
  1679. return -EINVAL;
  1680. if (var->yoffset > (info->var.yres_virtual - info->var.yres))
  1681. return -EINVAL;
  1682. if (info->fix.xpanstep)
  1683. info->var.xoffset =
  1684. (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
  1685. if (info->fix.ypanstep)
  1686. info->var.yoffset =
  1687. (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
  1688. /* "UPDT" */
  1689. if (var->reserved[0] == 0x54445055) {
  1690. dirty.xoffset = var->reserved[1] & 0xffff;
  1691. dirty.yoffset = (var->reserved[1] >> 16) & 0xffff;
  1692. if ((var->reserved[2] & 0xffff) <= dirty.xoffset)
  1693. return -EINVAL;
  1694. if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset)
  1695. return -EINVAL;
  1696. dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset;
  1697. dirty.height =
  1698. ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset;
  1699. info->var.yoffset = var->yoffset;
  1700. if (dirty.xoffset < 0)
  1701. return -EINVAL;
  1702. if (dirty.yoffset < 0)
  1703. return -EINVAL;
  1704. if ((dirty.xoffset + dirty.width) > info->var.xres)
  1705. return -EINVAL;
  1706. if ((dirty.yoffset + dirty.height) > info->var.yres)
  1707. return -EINVAL;
  1708. if ((dirty.width <= 0) || (dirty.height <= 0))
  1709. return -EINVAL;
  1710. dirtyPtr = &dirty;
  1711. }
  1712. complete(&mfd->msmfb_update_notify);
  1713. mutex_lock(&msm_fb_notify_update_sem);
  1714. if (mfd->msmfb_no_update_notify_timer.function)
  1715. del_timer(&mfd->msmfb_no_update_notify_timer);
  1716. mfd->msmfb_no_update_notify_timer.expires = jiffies + (2 * HZ);
  1717. add_timer(&mfd->msmfb_no_update_notify_timer);
  1718. mutex_unlock(&msm_fb_notify_update_sem);
  1719. down(&msm_fb_pan_sem);
  1720. msm_fb_wait_for_fence(mfd);
  1721. if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
  1722. mdp_set_dma_pan_info(info, NULL, TRUE);
  1723. if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
  1724. pr_err("%s: can't turn on display!\n", __func__);
  1725. if (mfd->timeline) {
  1726. sw_sync_timeline_inc(mfd->timeline, 2);
  1727. mfd->timeline_value += 2;
  1728. }
  1729. return -EINVAL;
  1730. }
  1731. }
  1732. mdp_set_dma_pan_info(info, dirtyPtr,
  1733. (var->activate & FB_ACTIVATE_VBL));
  1734. /* async call */
  1735. mdp_dma_pan_update(info);
  1736. msm_fb_signal_timeline(mfd);
  1737. up(&msm_fb_pan_sem);
  1738. if (unset_bl_level && !bl_updated)
  1739. schedule_delayed_work(&mfd->backlight_worker,
  1740. backlight_duration);
  1741. if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
  1742. mdp_free_splash_buffer(mfd);
  1743. ++mfd->panel_info.frame_count;
  1744. return 0;
  1745. }
  1746. static void msm_fb_commit_wq_handler(struct work_struct *work)
  1747. {
  1748. struct msm_fb_data_type *mfd;
  1749. struct fb_var_screeninfo *var;
  1750. struct fb_info *info;
  1751. struct msm_fb_backup_type *fb_backup;
  1752. mfd = container_of(work, struct msm_fb_data_type, commit_work);
  1753. fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
  1754. var = &fb_backup->var;
  1755. info = &fb_backup->info;
  1756. msm_fb_pan_display_sub(var, info);
  1757. mutex_lock(&mfd->sync_mutex);
  1758. mfd->is_committing = 0;
  1759. complete_all(&mfd->commit_comp);
  1760. mutex_unlock(&mfd->sync_mutex);
  1761. }
  1762. static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  1763. {
  1764. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  1765. msm_fb_pan_idle(mfd);
  1766. if (var->rotate != FB_ROTATE_UR)
  1767. return -EINVAL;
  1768. if (var->grayscale != info->var.grayscale)
  1769. return -EINVAL;
  1770. switch (var->bits_per_pixel) {
  1771. case 16:
  1772. if ((var->green.offset != 5) ||
  1773. !((var->blue.offset == 11)
  1774. || (var->blue.offset == 0)) ||
  1775. !((var->red.offset == 11)
  1776. || (var->red.offset == 0)) ||
  1777. (var->blue.length != 5) ||
  1778. (var->green.length != 6) ||
  1779. (var->red.length != 5) ||
  1780. (var->blue.msb_right != 0) ||
  1781. (var->green.msb_right != 0) ||
  1782. (var->red.msb_right != 0) ||
  1783. (var->transp.offset != 0) ||
  1784. (var->transp.length != 0))
  1785. return -EINVAL;
  1786. break;
  1787. case 24:
  1788. if ((var->blue.offset != 0) ||
  1789. (var->green.offset != 8) ||
  1790. (var->red.offset != 16) ||
  1791. (var->blue.length != 8) ||
  1792. (var->green.length != 8) ||
  1793. (var->red.length != 8) ||
  1794. (var->blue.msb_right != 0) ||
  1795. (var->green.msb_right != 0) ||
  1796. (var->red.msb_right != 0) ||
  1797. !(((var->transp.offset == 0) &&
  1798. (var->transp.length == 0)) ||
  1799. ((var->transp.offset == 24) &&
  1800. (var->transp.length == 8))))
  1801. return -EINVAL;
  1802. break;
  1803. case 32:
  1804. /* Figure out if the user meant RGBA or ARGB
  1805. and verify the position of the RGB components */
  1806. if (var->transp.offset == 24) {
  1807. if ((var->blue.offset != 0) ||
  1808. (var->green.offset != 8) ||
  1809. (var->red.offset != 16))
  1810. return -EINVAL;
  1811. } else if (var->transp.offset == 0) {
  1812. if ((var->blue.offset != 8) ||
  1813. (var->green.offset != 16) ||
  1814. (var->red.offset != 24))
  1815. return -EINVAL;
  1816. } else
  1817. return -EINVAL;
  1818. /* Check the common values for both RGBA and ARGB */
  1819. if ((var->blue.length != 8) ||
  1820. (var->green.length != 8) ||
  1821. (var->red.length != 8) ||
  1822. (var->transp.length != 8) ||
  1823. (var->blue.msb_right != 0) ||
  1824. (var->green.msb_right != 0) ||
  1825. (var->red.msb_right != 0))
  1826. return -EINVAL;
  1827. break;
  1828. default:
  1829. return -EINVAL;
  1830. }
  1831. if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0))
  1832. return -EINVAL;
  1833. if (!bf_supported ||
  1834. (info->node != 1 && info->node != 2))
  1835. if (info->fix.smem_len <
  1836. (var->xres_virtual*
  1837. var->yres_virtual*
  1838. (var->bits_per_pixel/8)))
  1839. return -EINVAL;
  1840. if ((var->xres == 0) || (var->yres == 0))
  1841. return -EINVAL;
  1842. if (var->xoffset > (var->xres_virtual - var->xres))
  1843. return -EINVAL;
  1844. if (var->yoffset > (var->yres_virtual - var->yres))
  1845. return -EINVAL;
  1846. return 0;
  1847. }
  1848. int msm_fb_check_frame_rate(struct msm_fb_data_type *mfd
  1849. , struct fb_info *info)
  1850. {
  1851. int panel_height, panel_width, var_frame_rate, fps_mod;
  1852. struct fb_var_screeninfo *var = &info->var;
  1853. fps_mod = 0;
  1854. if ((mfd->panel_info.type == DTV_PANEL) ||
  1855. (mfd->panel_info.type == HDMI_PANEL)) {
  1856. panel_height = var->yres + var->upper_margin +
  1857. var->vsync_len + var->lower_margin;
  1858. panel_width = var->xres + var->right_margin +
  1859. var->hsync_len + var->left_margin;
  1860. var_frame_rate = ((var->pixclock)/(panel_height * panel_width));
  1861. if (mfd->var_frame_rate != var_frame_rate) {
  1862. fps_mod = 1;
  1863. mfd->var_frame_rate = var_frame_rate;
  1864. }
  1865. }
  1866. return fps_mod;
  1867. }
  1868. static int msm_fb_set_par(struct fb_info *info)
  1869. {
  1870. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  1871. struct fb_var_screeninfo *var = &info->var;
  1872. int old_imgType;
  1873. int blank = 0;
  1874. msm_fb_pan_idle(mfd);
  1875. old_imgType = mfd->fb_imgType;
  1876. switch (var->bits_per_pixel) {
  1877. case 16:
  1878. if (var->red.offset == 0)
  1879. mfd->fb_imgType = MDP_BGR_565;
  1880. else
  1881. mfd->fb_imgType = MDP_RGB_565;
  1882. break;
  1883. case 24:
  1884. if ((var->transp.offset == 0) && (var->transp.length == 0))
  1885. mfd->fb_imgType = MDP_RGB_888;
  1886. else if ((var->transp.offset == 24) &&
  1887. (var->transp.length == 8)) {
  1888. mfd->fb_imgType = MDP_ARGB_8888;
  1889. info->var.bits_per_pixel = 32;
  1890. }
  1891. break;
  1892. case 32:
  1893. if ((var->transp.offset == 24) && (var->blue.offset == 0))
  1894. mfd->fb_imgType = MDP_BGRA_8888;
  1895. else if (var->transp.offset == 24)
  1896. mfd->fb_imgType = MDP_ARGB_8888;
  1897. else
  1898. mfd->fb_imgType = MDP_RGBA_8888;
  1899. break;
  1900. default:
  1901. return -EINVAL;
  1902. }
  1903. if ((mfd->var_pixclock != var->pixclock) ||
  1904. (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) ||
  1905. (mfd->var_pixclock != var->pixclock) ||
  1906. (mfd->var_xres != var->xres) ||
  1907. (mfd->var_yres != var->yres) ||
  1908. (msm_fb_check_frame_rate(mfd, info))))) {
  1909. mfd->var_xres = var->xres;
  1910. mfd->var_yres = var->yres;
  1911. mfd->var_pixclock = var->pixclock;
  1912. blank = 1;
  1913. }
  1914. mfd->fbi->fix.line_length = msm_fb_line_length(mfd->index, var->xres,
  1915. var->bits_per_pixel/8);
  1916. if (blank) {
  1917. msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
  1918. if (mfd->update_panel_info)
  1919. mfd->update_panel_info(mfd);
  1920. msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable);
  1921. }
  1922. return 0;
  1923. }
  1924. static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd)
  1925. {
  1926. if (mfd->hw_refresh)
  1927. return -EPERM;
  1928. if (mfd->sw_currently_refreshing) {
  1929. down(&mfd->sem);
  1930. mfd->sw_currently_refreshing = FALSE;
  1931. up(&mfd->sem);
  1932. /* wait until the refresher finishes the last job */
  1933. wait_for_completion_killable(&mfd->refresher_comp);
  1934. }
  1935. return 0;
  1936. }
  1937. int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd)
  1938. {
  1939. boolean do_refresh;
  1940. if (mfd->hw_refresh)
  1941. return -EPERM;
  1942. down(&mfd->sem);
  1943. if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) {
  1944. do_refresh = TRUE;
  1945. mfd->sw_currently_refreshing = TRUE;
  1946. } else {
  1947. do_refresh = FALSE;
  1948. }
  1949. up(&mfd->sem);
  1950. if (do_refresh)
  1951. mdp_refresh_screen((unsigned long)mfd);
  1952. return 0;
  1953. }
  1954. #if defined CONFIG_FB_MSM_MDP31
  1955. static int mdp_blit_split_height(struct fb_info *info,
  1956. struct mdp_blit_req *req)
  1957. {
  1958. int ret;
  1959. struct mdp_blit_req splitreq;
  1960. int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
  1961. int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
  1962. splitreq = *req;
  1963. /* break dest roi at height*/
  1964. d_x_0 = d_x_1 = req->dst_rect.x;
  1965. d_w_0 = d_w_1 = req->dst_rect.w;
  1966. d_y_0 = req->dst_rect.y;
  1967. if (req->dst_rect.h % 32 == 3)
  1968. d_h_1 = (req->dst_rect.h - 3) / 2 - 1;
  1969. else if (req->dst_rect.h % 32 == 2)
  1970. d_h_1 = (req->dst_rect.h - 2) / 2 - 6;
  1971. else
  1972. d_h_1 = (req->dst_rect.h - 1) / 2 - 1;
  1973. d_h_0 = req->dst_rect.h - d_h_1;
  1974. d_y_1 = d_y_0 + d_h_0;
  1975. if (req->dst_rect.h == 3) {
  1976. d_h_1 = 2;
  1977. d_h_0 = 2;
  1978. d_y_1 = d_y_0 + 1;
  1979. }
  1980. /* blit first region */
  1981. if (((splitreq.flags & 0x07) == 0x04) ||
  1982. ((splitreq.flags & 0x07) == 0x0)) {
  1983. if (splitreq.flags & MDP_ROT_90) {
  1984. s_y_0 = s_y_1 = req->src_rect.y;
  1985. s_h_0 = s_h_1 = req->src_rect.h;
  1986. s_x_0 = req->src_rect.x;
  1987. s_w_1 = (req->src_rect.w * d_h_1) / req->dst_rect.h;
  1988. s_w_0 = req->src_rect.w - s_w_1;
  1989. s_x_1 = s_x_0 + s_w_0;
  1990. if (d_h_1 >= 8 * s_w_1) {
  1991. s_w_1++;
  1992. s_x_1--;
  1993. }
  1994. } else {
  1995. s_x_0 = s_x_1 = req->src_rect.x;
  1996. s_w_0 = s_w_1 = req->src_rect.w;
  1997. s_y_0 = req->src_rect.y;
  1998. s_h_1 = (req->src_rect.h * d_h_1) / req->dst_rect.h;
  1999. s_h_0 = req->src_rect.h - s_h_1;
  2000. s_y_1 = s_y_0 + s_h_0;
  2001. if (d_h_1 >= 8 * s_h_1) {
  2002. s_h_1++;
  2003. s_y_1--;
  2004. }
  2005. }
  2006. splitreq.src_rect.h = s_h_0;
  2007. splitreq.src_rect.y = s_y_0;
  2008. splitreq.dst_rect.h = d_h_0;
  2009. splitreq.dst_rect.y = d_y_0;
  2010. splitreq.src_rect.x = s_x_0;
  2011. splitreq.src_rect.w = s_w_0;
  2012. splitreq.dst_rect.x = d_x_0;
  2013. splitreq.dst_rect.w = d_w_0;
  2014. } else {
  2015. if (splitreq.flags & MDP_ROT_90) {
  2016. s_y_0 = s_y_1 = req->src_rect.y;
  2017. s_h_0 = s_h_1 = req->src_rect.h;
  2018. s_x_0 = req->src_rect.x;
  2019. s_w_1 = (req->src_rect.w * d_h_0) / req->dst_rect.h;
  2020. s_w_0 = req->src_rect.w - s_w_1;
  2021. s_x_1 = s_x_0 + s_w_0;
  2022. if (d_h_0 >= 8 * s_w_1) {
  2023. s_w_1++;
  2024. s_x_1--;
  2025. }
  2026. } else {
  2027. s_x_0 = s_x_1 = req->src_rect.x;
  2028. s_w_0 = s_w_1 = req->src_rect.w;
  2029. s_y_0 = req->src_rect.y;
  2030. s_h_1 = (req->src_rect.h * d_h_0) / req->dst_rect.h;
  2031. s_h_0 = req->src_rect.h - s_h_1;
  2032. s_y_1 = s_y_0 + s_h_0;
  2033. if (d_h_0 >= 8 * s_h_1) {
  2034. s_h_1++;
  2035. s_y_1--;
  2036. }
  2037. }
  2038. splitreq.src_rect.h = s_h_0;
  2039. splitreq.src_rect.y = s_y_0;
  2040. splitreq.dst_rect.h = d_h_1;
  2041. splitreq.dst_rect.y = d_y_1;
  2042. splitreq.src_rect.x = s_x_0;
  2043. splitreq.src_rect.w = s_w_0;
  2044. splitreq.dst_rect.x = d_x_1;
  2045. splitreq.dst_rect.w = d_w_1;
  2046. }
  2047. ret = mdp_ppp_blit(info, &splitreq);
  2048. if (ret)
  2049. return ret;
  2050. /* blit second region */
  2051. if (((splitreq.flags & 0x07) == 0x04) ||
  2052. ((splitreq.flags & 0x07) == 0x0)) {
  2053. splitreq.src_rect.h = s_h_1;
  2054. splitreq.src_rect.y = s_y_1;
  2055. splitreq.dst_rect.h = d_h_1;
  2056. splitreq.dst_rect.y = d_y_1;
  2057. splitreq.src_rect.x = s_x_1;
  2058. splitreq.src_rect.w = s_w_1;
  2059. splitreq.dst_rect.x = d_x_1;
  2060. splitreq.dst_rect.w = d_w_1;
  2061. } else {
  2062. splitreq.src_rect.h = s_h_1;
  2063. splitreq.src_rect.y = s_y_1;
  2064. splitreq.dst_rect.h = d_h_0;
  2065. splitreq.dst_rect.y = d_y_0;
  2066. splitreq.src_rect.x = s_x_1;
  2067. splitreq.src_rect.w = s_w_1;
  2068. splitreq.dst_rect.x = d_x_0;
  2069. splitreq.dst_rect.w = d_w_0;
  2070. }
  2071. ret = mdp_ppp_blit(info, &splitreq);
  2072. return ret;
  2073. }
  2074. #endif
  2075. int mdp_blit(struct fb_info *info, struct mdp_blit_req *req)
  2076. {
  2077. int ret;
  2078. #if defined CONFIG_FB_MSM_MDP31 || defined CONFIG_FB_MSM_MDP30
  2079. unsigned int remainder = 0, is_bpp_4 = 0;
  2080. struct mdp_blit_req splitreq;
  2081. int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
  2082. int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
  2083. if (req->flags & MDP_ROT_90) {
  2084. if (((req->dst_rect.h == 1) && ((req->src_rect.w != 1) ||
  2085. (req->dst_rect.w != req->src_rect.h))) ||
  2086. ((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
  2087. (req->dst_rect.h != req->src_rect.w)))) {
  2088. printk(KERN_ERR "mpd_ppp: error scaling when size is 1!\n");
  2089. return -EINVAL;
  2090. }
  2091. } else {
  2092. if (((req->dst_rect.w == 1) && ((req->src_rect.w != 1) ||
  2093. (req->dst_rect.h != req->src_rect.h))) ||
  2094. ((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
  2095. (req->dst_rect.w != req->src_rect.w)))) {
  2096. printk(KERN_ERR "mpd_ppp: error scaling when size is 1!\n");
  2097. return -EINVAL;
  2098. }
  2099. }
  2100. #endif
  2101. if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
  2102. printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
  2103. return -EINVAL;
  2104. }
  2105. if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
  2106. return 0;
  2107. #if defined CONFIG_FB_MSM_MDP31
  2108. /* MDP width split workaround */
  2109. remainder = (req->dst_rect.w)%32;
  2110. ret = mdp_get_bytes_per_pixel(req->dst.format,
  2111. (struct msm_fb_data_type *)info->par);
  2112. if (ret <= 0) {
  2113. printk(KERN_ERR "mdp_ppp: incorrect bpp!\n");
  2114. return -EINVAL;
  2115. }
  2116. is_bpp_4 = (ret == 4) ? 1 : 0;
  2117. if ((is_bpp_4 && (remainder == 6 || remainder == 14 ||
  2118. remainder == 22 || remainder == 30)) || remainder == 3 ||
  2119. (remainder == 1 && req->dst_rect.w != 1) ||
  2120. (remainder == 2 && req->dst_rect.w != 2)) {
  2121. /* make new request as provide by user */
  2122. splitreq = *req;
  2123. /* break dest roi at width*/
  2124. d_y_0 = d_y_1 = req->dst_rect.y;
  2125. d_h_0 = d_h_1 = req->dst_rect.h;
  2126. d_x_0 = req->dst_rect.x;
  2127. if (remainder == 14)
  2128. d_w_1 = (req->dst_rect.w - 14) / 2 + 4;
  2129. else if (remainder == 22)
  2130. d_w_1 = (req->dst_rect.w - 22) / 2 + 10;
  2131. else if (remainder == 30)
  2132. d_w_1 = (req->dst_rect.w - 30) / 2 + 10;
  2133. else if (remainder == 6)
  2134. d_w_1 = req->dst_rect.w / 2 - 1;
  2135. else if (remainder == 3)
  2136. d_w_1 = (req->dst_rect.w - 3) / 2 - 1;
  2137. else if (remainder == 2)
  2138. d_w_1 = (req->dst_rect.w - 2) / 2 - 6;
  2139. else
  2140. d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
  2141. d_w_0 = req->dst_rect.w - d_w_1;
  2142. d_x_1 = d_x_0 + d_w_0;
  2143. if (req->dst_rect.w == 3) {
  2144. d_w_1 = 2;
  2145. d_w_0 = 2;
  2146. d_x_1 = d_x_0 + 1;
  2147. }
  2148. /* blit first region */
  2149. if (((splitreq.flags & 0x07) == 0x07) ||
  2150. ((splitreq.flags & 0x07) == 0x0)) {
  2151. if (splitreq.flags & MDP_ROT_90) {
  2152. s_x_0 = s_x_1 = req->src_rect.x;
  2153. s_w_0 = s_w_1 = req->src_rect.w;
  2154. s_y_0 = req->src_rect.y;
  2155. s_h_1 = (req->src_rect.h * d_w_1) /
  2156. req->dst_rect.w;
  2157. s_h_0 = req->src_rect.h - s_h_1;
  2158. s_y_1 = s_y_0 + s_h_0;
  2159. if (d_w_1 >= 8 * s_h_1) {
  2160. s_h_1++;
  2161. s_y_1--;
  2162. }
  2163. } else {
  2164. s_y_0 = s_y_1 = req->src_rect.y;
  2165. s_h_0 = s_h_1 = req->src_rect.h;
  2166. s_x_0 = req->src_rect.x;
  2167. s_w_1 = (req->src_rect.w * d_w_1) /
  2168. req->dst_rect.w;
  2169. s_w_0 = req->src_rect.w - s_w_1;
  2170. s_x_1 = s_x_0 + s_w_0;
  2171. if (d_w_1 >= 8 * s_w_1) {
  2172. s_w_1++;
  2173. s_x_1--;
  2174. }
  2175. }
  2176. splitreq.src_rect.h = s_h_0;
  2177. splitreq.src_rect.y = s_y_0;
  2178. splitreq.dst_rect.h = d_h_0;
  2179. splitreq.dst_rect.y = d_y_0;
  2180. splitreq.src_rect.x = s_x_0;
  2181. splitreq.src_rect.w = s_w_0;
  2182. splitreq.dst_rect.x = d_x_0;
  2183. splitreq.dst_rect.w = d_w_0;
  2184. } else {
  2185. if (splitreq.flags & MDP_ROT_90) {
  2186. s_x_0 = s_x_1 = req->src_rect.x;
  2187. s_w_0 = s_w_1 = req->src_rect.w;
  2188. s_y_0 = req->src_rect.y;
  2189. s_h_1 = (req->src_rect.h * d_w_0) /
  2190. req->dst_rect.w;
  2191. s_h_0 = req->src_rect.h - s_h_1;
  2192. s_y_1 = s_y_0 + s_h_0;
  2193. if (d_w_0 >= 8 * s_h_1) {
  2194. s_h_1++;
  2195. s_y_1--;
  2196. }
  2197. } else {
  2198. s_y_0 = s_y_1 = req->src_rect.y;
  2199. s_h_0 = s_h_1 = req->src_rect.h;
  2200. s_x_0 = req->src_rect.x;
  2201. s_w_1 = (req->src_rect.w * d_w_0) /
  2202. req->dst_rect.w;
  2203. s_w_0 = req->src_rect.w - s_w_1;
  2204. s_x_1 = s_x_0 + s_w_0;
  2205. if (d_w_0 >= 8 * s_w_1) {
  2206. s_w_1++;
  2207. s_x_1--;
  2208. }
  2209. }
  2210. splitreq.src_rect.h = s_h_0;
  2211. splitreq.src_rect.y = s_y_0;
  2212. splitreq.dst_rect.h = d_h_1;
  2213. splitreq.dst_rect.y = d_y_1;
  2214. splitreq.src_rect.x = s_x_0;
  2215. splitreq.src_rect.w = s_w_0;
  2216. splitreq.dst_rect.x = d_x_1;
  2217. splitreq.dst_rect.w = d_w_1;
  2218. }
  2219. if ((splitreq.dst_rect.h % 32 == 3) ||
  2220. ((req->dst_rect.h % 32) == 1 && req->dst_rect.h != 1) ||
  2221. ((req->dst_rect.h % 32) == 2 && req->dst_rect.h != 2))
  2222. ret = mdp_blit_split_height(info, &splitreq);
  2223. else
  2224. ret = mdp_ppp_blit(info, &splitreq);
  2225. if (ret)
  2226. return ret;
  2227. /* blit second region */
  2228. if (((splitreq.flags & 0x07) == 0x07) ||
  2229. ((splitreq.flags & 0x07) == 0x0)) {
  2230. splitreq.src_rect.h = s_h_1;
  2231. splitreq.src_rect.y = s_y_1;
  2232. splitreq.dst_rect.h = d_h_1;
  2233. splitreq.dst_rect.y = d_y_1;
  2234. splitreq.src_rect.x = s_x_1;
  2235. splitreq.src_rect.w = s_w_1;
  2236. splitreq.dst_rect.x = d_x_1;
  2237. splitreq.dst_rect.w = d_w_1;
  2238. } else {
  2239. splitreq.src_rect.h = s_h_1;
  2240. splitreq.src_rect.y = s_y_1;
  2241. splitreq.dst_rect.h = d_h_0;
  2242. splitreq.dst_rect.y = d_y_0;
  2243. splitreq.src_rect.x = s_x_1;
  2244. splitreq.src_rect.w = s_w_1;
  2245. splitreq.dst_rect.x = d_x_0;
  2246. splitreq.dst_rect.w = d_w_0;
  2247. }
  2248. if (((splitreq.dst_rect.h % 32) == 3) ||
  2249. ((req->dst_rect.h % 32) == 1 && req->dst_rect.h != 1) ||
  2250. ((req->dst_rect.h % 32) == 2 && req->dst_rect.h != 2))
  2251. ret = mdp_blit_split_height(info, &splitreq);
  2252. else
  2253. ret = mdp_ppp_blit(info, &splitreq);
  2254. if (ret)
  2255. return ret;
  2256. } else if ((req->dst_rect.h % 32) == 3 ||
  2257. ((req->dst_rect.h % 32) == 1 && req->dst_rect.h != 1) ||
  2258. ((req->dst_rect.h % 32) == 2 && req->dst_rect.h != 2))
  2259. ret = mdp_blit_split_height(info, req);
  2260. else
  2261. ret = mdp_ppp_blit(info, req);
  2262. return ret;
  2263. #elif defined CONFIG_FB_MSM_MDP30
  2264. /* MDP width split workaround */
  2265. remainder = (req->dst_rect.w)%16;
  2266. ret = mdp_get_bytes_per_pixel(req->dst.format,
  2267. (struct msm_fb_data_type *)info->par);
  2268. if (ret <= 0) {
  2269. printk(KERN_ERR "mdp_ppp: incorrect bpp!\n");
  2270. return -EINVAL;
  2271. }
  2272. is_bpp_4 = (ret == 4) ? 1 : 0;
  2273. if ((is_bpp_4 && (remainder == 6 || remainder == 14))) {
  2274. /* make new request as provide by user */
  2275. splitreq = *req;
  2276. /* break dest roi at width*/
  2277. d_y_0 = d_y_1 = req->dst_rect.y;
  2278. d_h_0 = d_h_1 = req->dst_rect.h;
  2279. d_x_0 = req->dst_rect.x;
  2280. if (remainder == 14 || remainder == 6)
  2281. d_w_1 = req->dst_rect.w / 2;
  2282. else
  2283. d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
  2284. d_w_0 = req->dst_rect.w - d_w_1;
  2285. d_x_1 = d_x_0 + d_w_0;
  2286. /* blit first region */
  2287. if (((splitreq.flags & 0x07) == 0x07) ||
  2288. ((splitreq.flags & 0x07) == 0x05) ||
  2289. ((splitreq.flags & 0x07) == 0x02) ||
  2290. ((splitreq.flags & 0x07) == 0x0)) {
  2291. if (splitreq.flags & MDP_ROT_90) {
  2292. s_x_0 = s_x_1 = req->src_rect.x;
  2293. s_w_0 = s_w_1 = req->src_rect.w;
  2294. s_y_0 = req->src_rect.y;
  2295. s_h_1 = (req->src_rect.h * d_w_1) /
  2296. req->dst_rect.w;
  2297. s_h_0 = req->src_rect.h - s_h_1;
  2298. s_y_1 = s_y_0 + s_h_0;
  2299. if (d_w_1 >= 8 * s_h_1) {
  2300. s_h_1++;
  2301. s_y_1--;
  2302. }
  2303. } else {
  2304. s_y_0 = s_y_1 = req->src_rect.y;
  2305. s_h_0 = s_h_1 = req->src_rect.h;
  2306. s_x_0 = req->src_rect.x;
  2307. s_w_1 = (req->src_rect.w * d_w_1) /
  2308. req->dst_rect.w;
  2309. s_w_0 = req->src_rect.w - s_w_1;
  2310. s_x_1 = s_x_0 + s_w_0;
  2311. if (d_w_1 >= 8 * s_w_1) {
  2312. s_w_1++;
  2313. s_x_1--;
  2314. }
  2315. }
  2316. splitreq.src_rect.h = s_h_0;
  2317. splitreq.src_rect.y = s_y_0;
  2318. splitreq.dst_rect.h = d_h_0;
  2319. splitreq.dst_rect.y = d_y_0;
  2320. splitreq.src_rect.x = s_x_0;
  2321. splitreq.src_rect.w = s_w_0;
  2322. splitreq.dst_rect.x = d_x_0;
  2323. splitreq.dst_rect.w = d_w_0;
  2324. } else {
  2325. if (splitreq.flags & MDP_ROT_90) {
  2326. s_x_0 = s_x_1 = req->src_rect.x;
  2327. s_w_0 = s_w_1 = req->src_rect.w;
  2328. s_y_0 = req->src_rect.y;
  2329. s_h_1 = (req->src_rect.h * d_w_0) /
  2330. req->dst_rect.w;
  2331. s_h_0 = req->src_rect.h - s_h_1;
  2332. s_y_1 = s_y_0 + s_h_0;
  2333. if (d_w_0 >= 8 * s_h_1) {
  2334. s_h_1++;
  2335. s_y_1--;
  2336. }
  2337. } else {
  2338. s_y_0 = s_y_1 = req->src_rect.y;
  2339. s_h_0 = s_h_1 = req->src_rect.h;
  2340. s_x_0 = req->src_rect.x;
  2341. s_w_1 = (req->src_rect.w * d_w_0) /
  2342. req->dst_rect.w;
  2343. s_w_0 = req->src_rect.w - s_w_1;
  2344. s_x_1 = s_x_0 + s_w_0;
  2345. if (d_w_0 >= 8 * s_w_1) {
  2346. s_w_1++;
  2347. s_x_1--;
  2348. }
  2349. }
  2350. splitreq.src_rect.h = s_h_0;
  2351. splitreq.src_rect.y = s_y_0;
  2352. splitreq.dst_rect.h = d_h_1;
  2353. splitreq.dst_rect.y = d_y_1;
  2354. splitreq.src_rect.x = s_x_0;
  2355. splitreq.src_rect.w = s_w_0;
  2356. splitreq.dst_rect.x = d_x_1;
  2357. splitreq.dst_rect.w = d_w_1;
  2358. }
  2359. /* No need to split in height */
  2360. ret = mdp_ppp_blit(info, &splitreq);
  2361. if (ret)
  2362. return ret;
  2363. /* blit second region */
  2364. if (((splitreq.flags & 0x07) == 0x07) ||
  2365. ((splitreq.flags & 0x07) == 0x05) ||
  2366. ((splitreq.flags & 0x07) == 0x02) ||
  2367. ((splitreq.flags & 0x07) == 0x0)) {
  2368. splitreq.src_rect.h = s_h_1;
  2369. splitreq.src_rect.y = s_y_1;
  2370. splitreq.dst_rect.h = d_h_1;
  2371. splitreq.dst_rect.y = d_y_1;
  2372. splitreq.src_rect.x = s_x_1;
  2373. splitreq.src_rect.w = s_w_1;
  2374. splitreq.dst_rect.x = d_x_1;
  2375. splitreq.dst_rect.w = d_w_1;
  2376. } else {
  2377. splitreq.src_rect.h = s_h_1;
  2378. splitreq.src_rect.y = s_y_1;
  2379. splitreq.dst_rect.h = d_h_0;
  2380. splitreq.dst_rect.y = d_y_0;
  2381. splitreq.src_rect.x = s_x_1;
  2382. splitreq.src_rect.w = s_w_1;
  2383. splitreq.dst_rect.x = d_x_0;
  2384. splitreq.dst_rect.w = d_w_0;
  2385. }
  2386. /* No need to split in height ... just width */
  2387. ret = mdp_ppp_blit(info, &splitreq);
  2388. if (ret)
  2389. return ret;
  2390. } else
  2391. ret = mdp_ppp_blit(info, req);
  2392. return ret;
  2393. #else
  2394. ret = mdp_ppp_blit(info, req);
  2395. return ret;
  2396. #endif
  2397. }
  2398. typedef void (*msm_dma_barrier_function_pointer) (void *, size_t);
  2399. static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info,
  2400. struct mdp_img *img, struct mdp_rect *rect,
  2401. msm_dma_barrier_function_pointer dma_barrier_fp
  2402. )
  2403. {
  2404. /*
  2405. * Compute the start and end addresses of the rectangles.
  2406. * NOTE: As currently implemented, the data between
  2407. * the end of one row and the start of the next is
  2408. * included in the address range rather than
  2409. * doing multiple calls for each row.
  2410. */
  2411. unsigned long start;
  2412. size_t size;
  2413. char * const pmem_start = info->screen_base;
  2414. int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format,
  2415. (struct msm_fb_data_type *)info->par);
  2416. if (bytes_per_pixel <= 0) {
  2417. printk(KERN_ERR "%s incorrect bpp!\n", __func__);
  2418. return;
  2419. }
  2420. start = (unsigned long)pmem_start + img->offset +
  2421. (img->width * rect->y + rect->x) * bytes_per_pixel;
  2422. size = (rect->h * img->width + rect->w) * bytes_per_pixel;
  2423. (*dma_barrier_fp) ((void *) start, size);
  2424. }
  2425. static inline void msm_dma_nc_pre(void)
  2426. {
  2427. dmb();
  2428. }
  2429. static inline void msm_dma_wt_pre(void)
  2430. {
  2431. dmb();
  2432. }
  2433. static inline void msm_dma_todevice_wb_pre(void *start, size_t size)
  2434. {
  2435. dma_cache_pre_ops(start, size, DMA_TO_DEVICE);
  2436. }
  2437. static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size)
  2438. {
  2439. dma_cache_pre_ops(start, size, DMA_FROM_DEVICE);
  2440. }
  2441. static inline void msm_dma_nc_post(void)
  2442. {
  2443. dmb();
  2444. }
  2445. static inline void msm_dma_fromdevice_wt_post(void *start, size_t size)
  2446. {
  2447. dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
  2448. }
  2449. static inline void msm_dma_todevice_wb_post(void *start, size_t size)
  2450. {
  2451. dma_cache_post_ops(start, size, DMA_TO_DEVICE);
  2452. }
  2453. static inline void msm_dma_fromdevice_wb_post(void *start, size_t size)
  2454. {
  2455. dma_cache_post_ops(start, size, DMA_FROM_DEVICE);
  2456. }
  2457. /*
  2458. * Do the write barriers required to guarantee data is committed to RAM
  2459. * (from CPU cache or internal buffers) before a DMA operation starts.
  2460. * NOTE: As currently implemented, the data between
  2461. * the end of one row and the start of the next is
  2462. * included in the address range rather than
  2463. * doing multiple calls for each row.
  2464. */
  2465. static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info,
  2466. struct mdp_blit_req *req_list,
  2467. int req_list_count)
  2468. {
  2469. #ifdef CONFIG_ARCH_QSD8X50
  2470. int i;
  2471. /*
  2472. * Normally, do the requested barriers for each address
  2473. * range that corresponds to a rectangle.
  2474. *
  2475. * But if at least one write barrier is requested for data
  2476. * going to or from the device but no address range is
  2477. * needed for that barrier, then do the barrier, but do it
  2478. * only once, no matter how many requests there are.
  2479. */
  2480. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  2481. switch (mfd->mdp_fb_page_protection) {
  2482. default:
  2483. case MDP_FB_PAGE_PROTECTION_NONCACHED:
  2484. case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
  2485. /*
  2486. * The following barrier is only done at most once,
  2487. * since further calls would be redundant.
  2488. */
  2489. for (i = 0; i < req_list_count; i++) {
  2490. if (!(req_list[i].flags
  2491. & MDP_NO_DMA_BARRIER_START)) {
  2492. msm_dma_nc_pre();
  2493. break;
  2494. }
  2495. }
  2496. break;
  2497. case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
  2498. /*
  2499. * The following barrier is only done at most once,
  2500. * since further calls would be redundant.
  2501. */
  2502. for (i = 0; i < req_list_count; i++) {
  2503. if (!(req_list[i].flags
  2504. & MDP_NO_DMA_BARRIER_START)) {
  2505. msm_dma_wt_pre();
  2506. break;
  2507. }
  2508. }
  2509. break;
  2510. case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
  2511. case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
  2512. for (i = 0; i < req_list_count; i++) {
  2513. if (!(req_list[i].flags &
  2514. MDP_NO_DMA_BARRIER_START)) {
  2515. msm_fb_dma_barrier_for_rect(info,
  2516. &(req_list[i].src),
  2517. &(req_list[i].src_rect),
  2518. msm_dma_todevice_wb_pre
  2519. );
  2520. msm_fb_dma_barrier_for_rect(info,
  2521. &(req_list[i].dst),
  2522. &(req_list[i].dst_rect),
  2523. msm_dma_todevice_wb_pre
  2524. );
  2525. }
  2526. }
  2527. break;
  2528. }
  2529. #else
  2530. dmb();
  2531. #endif
  2532. }
  2533. /*
  2534. * Do the write barriers required to guarantee data will be re-read from RAM by
  2535. * the CPU after a DMA operation ends.
  2536. * NOTE: As currently implemented, the data between
  2537. * the end of one row and the start of the next is
  2538. * included in the address range rather than
  2539. * doing multiple calls for each row.
  2540. */
  2541. static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info,
  2542. struct mdp_blit_req *req_list,
  2543. int req_list_count)
  2544. {
  2545. #ifdef CONFIG_ARCH_QSD8X50
  2546. int i;
  2547. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  2548. switch (mfd->mdp_fb_page_protection) {
  2549. default:
  2550. case MDP_FB_PAGE_PROTECTION_NONCACHED:
  2551. case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
  2552. /*
  2553. * The following barrier is only done at most once,
  2554. * since further calls would be redundant.
  2555. */
  2556. for (i = 0; i < req_list_count; i++) {
  2557. if (!(req_list[i].flags
  2558. & MDP_NO_DMA_BARRIER_END)) {
  2559. msm_dma_nc_post();
  2560. break;
  2561. }
  2562. }
  2563. break;
  2564. case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
  2565. for (i = 0; i < req_list_count; i++) {
  2566. if (!(req_list[i].flags &
  2567. MDP_NO_DMA_BARRIER_END)) {
  2568. msm_fb_dma_barrier_for_rect(info,
  2569. &(req_list[i].dst),
  2570. &(req_list[i].dst_rect),
  2571. msm_dma_fromdevice_wt_post
  2572. );
  2573. }
  2574. }
  2575. break;
  2576. case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
  2577. case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
  2578. for (i = 0; i < req_list_count; i++) {
  2579. if (!(req_list[i].flags &
  2580. MDP_NO_DMA_BARRIER_END)) {
  2581. msm_fb_dma_barrier_for_rect(info,
  2582. &(req_list[i].dst),
  2583. &(req_list[i].dst_rect),
  2584. msm_dma_fromdevice_wb_post
  2585. );
  2586. }
  2587. }
  2588. break;
  2589. }
  2590. #else
  2591. dmb();
  2592. #endif
  2593. }
  2594. /*
  2595. * NOTE: The userspace issues blit operations in a sequence, the sequence
  2596. * start with a operation marked START and ends in an operation marked
  2597. * END. It is guranteed by the userspace that all the blit operations
  2598. * between START and END are only within the regions of areas designated
  2599. * by the START and END operations and that the userspace doesnt modify
  2600. * those areas. Hence it would be enough to perform barrier/cache operations
  2601. * only on the START and END operations.
  2602. */
  2603. static int msmfb_blit(struct fb_info *info, void __user *p)
  2604. {
  2605. /*
  2606. * CAUTION: The names of the struct types intentionally *DON'T* match
  2607. * the names of the variables declared -- they appear to be swapped.
  2608. * Read the code carefully and you should see that the variable names
  2609. * make sense.
  2610. */
  2611. const int MAX_LIST_WINDOW = 16;
  2612. struct mdp_blit_req req_list[MAX_LIST_WINDOW];
  2613. struct mdp_blit_req_list req_list_header;
  2614. int count, i, req_list_count;
  2615. if (bf_supported &&
  2616. (info->node == 1 || info->node == 2)) {
  2617. pr_err("%s: no pan display for fb%d.",
  2618. __func__, info->node);
  2619. return -EPERM;
  2620. }
  2621. /* Get the count size for the total BLIT request. */
  2622. if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
  2623. return -EFAULT;
  2624. p += sizeof(req_list_header);
  2625. count = req_list_header.count;
  2626. if (count < 0 || count >= MAX_BLIT_REQ)
  2627. return -EINVAL;
  2628. while (count > 0) {
  2629. /*
  2630. * Access the requests through a narrow window to decrease copy
  2631. * overhead and make larger requests accessible to the
  2632. * coherency management code.
  2633. * NOTE: The window size is intended to be larger than the
  2634. * typical request size, but not require more than 2
  2635. * kbytes of stack storage.
  2636. */
  2637. req_list_count = count;
  2638. if (req_list_count > MAX_LIST_WINDOW)
  2639. req_list_count = MAX_LIST_WINDOW;
  2640. if (copy_from_user(&req_list, p,
  2641. sizeof(struct mdp_blit_req)*req_list_count))
  2642. return -EFAULT;
  2643. /*
  2644. * Ensure that any data CPU may have previously written to
  2645. * internal state (but not yet committed to memory) is
  2646. * guaranteed to be committed to memory now.
  2647. */
  2648. msm_fb_ensure_memory_coherency_before_dma(info,
  2649. req_list, req_list_count);
  2650. /*
  2651. * Do the blit DMA, if required -- returning early only if
  2652. * there is a failure.
  2653. */
  2654. for (i = 0; i < req_list_count; i++) {
  2655. if (!(req_list[i].flags & MDP_NO_BLIT)) {
  2656. /* Do the actual blit. */
  2657. int ret = mdp_blit(info, &(req_list[i]));
  2658. /*
  2659. * Note that early returns don't guarantee
  2660. * memory coherency.
  2661. */
  2662. if (ret)
  2663. return ret;
  2664. }
  2665. }
  2666. /*
  2667. * Ensure that CPU cache and other internal CPU state is
  2668. * updated to reflect any change in memory modified by MDP blit
  2669. * DMA.
  2670. */
  2671. msm_fb_ensure_memory_coherency_after_dma(info,
  2672. req_list,
  2673. req_list_count);
  2674. /* Go to next window of requests. */
  2675. count -= req_list_count;
  2676. p += sizeof(struct mdp_blit_req)*req_list_count;
  2677. }
  2678. return 0;
  2679. }
  2680. static int msmfb_vsync_ctrl(struct fb_info *info, void __user *argp)
  2681. {
  2682. int enable, ret;
  2683. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  2684. ret = copy_from_user(&enable, argp, sizeof(enable));
  2685. if (ret) {
  2686. pr_err("%s:msmfb_overlay_vsync ioctl failed", __func__);
  2687. return ret;
  2688. }
  2689. if (mfd->vsync_ctrl)
  2690. mfd->vsync_ctrl(enable);
  2691. else {
  2692. pr_err("%s: Vsync IOCTL not supported", __func__);
  2693. return -EINVAL;
  2694. }
  2695. return 0;
  2696. }
  2697. #ifdef CONFIG_FB_MSM_OVERLAY
  2698. static int msmfb_overlay_get(struct fb_info *info, void __user *p)
  2699. {
  2700. struct mdp_overlay req;
  2701. int ret;
  2702. if (copy_from_user(&req, p, sizeof(req)))
  2703. return -EFAULT;
  2704. ret = mdp4_overlay_get(info, &req);
  2705. if (ret) {
  2706. printk(KERN_ERR "%s: ioctl failed \n",
  2707. __func__);
  2708. return ret;
  2709. }
  2710. if (copy_to_user(p, &req, sizeof(req))) {
  2711. printk(KERN_ERR "%s: copy2user failed \n",
  2712. __func__);
  2713. return -EFAULT;
  2714. }
  2715. return 0;
  2716. }
  2717. static int msmfb_overlay_set(struct fb_info *info, void __user *p)
  2718. {
  2719. struct mdp_overlay req;
  2720. int ret;
  2721. if (copy_from_user(&req, p, sizeof(req)))
  2722. return -EFAULT;
  2723. ret = mdp4_overlay_set(info, &req);
  2724. if (ret) {
  2725. printk(KERN_ERR "%s: ioctl failed, rc=%d\n",
  2726. __func__, ret);
  2727. return ret;
  2728. }
  2729. if (copy_to_user(p, &req, sizeof(req))) {
  2730. printk(KERN_ERR "%s: copy2user failed \n",
  2731. __func__);
  2732. return -EFAULT;
  2733. }
  2734. return 0;
  2735. }
  2736. static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp)
  2737. {
  2738. int ret, ndx;
  2739. struct msm_fb_data_type *mfd;
  2740. if (info == NULL || info->par == NULL) {
  2741. pr_err("%s info=%p or par is NULL\n", __func__, info);
  2742. return -ENODEV;
  2743. }
  2744. mfd = (struct msm_fb_data_type *)info->par;
  2745. ret = copy_from_user(&ndx, argp, sizeof(ndx));
  2746. if (ret) {
  2747. printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n",
  2748. __func__);
  2749. return ret;
  2750. }
  2751. /*
  2752. * If previous commit hasn't finished yet, unset cannot be started
  2753. * otherwise, previous scene will be corrupted.
  2754. */
  2755. msm_fb_pan_idle(mfd);
  2756. return mdp4_overlay_unset(info, ndx);
  2757. }
  2758. static int msmfb_overlay_vsync_ctrl(struct fb_info *info, void __user *argp)
  2759. {
  2760. int ret;
  2761. int enable;
  2762. ret = copy_from_user(&enable, argp, sizeof(enable));
  2763. if (ret) {
  2764. pr_err("%s:msmfb_overlay_vsync ioctl failed", __func__);
  2765. return ret;
  2766. }
  2767. ret = mdp4_overlay_vsync_ctrl(info, enable);
  2768. return ret;
  2769. }
  2770. static int msmfb_overlay_play_wait(struct fb_info *info, unsigned long *argp)
  2771. {
  2772. int ret;
  2773. struct msmfb_overlay_data req;
  2774. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  2775. if (mfd->overlay_play_enable == 0) /* nothing to do */
  2776. return 0;
  2777. ret = copy_from_user(&req, argp, sizeof(req));
  2778. if (ret) {
  2779. pr_err("%s:msmfb_overlay_wait ioctl failed", __func__);
  2780. return ret;
  2781. }
  2782. ret = mdp4_overlay_play_wait(info, &req);
  2783. return ret;
  2784. }
  2785. static int msmfb_overlay_commit(struct fb_info *info)
  2786. {
  2787. return mdp4_overlay_commit(info);
  2788. }
  2789. static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
  2790. {
  2791. int ret;
  2792. struct msmfb_overlay_data req;
  2793. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  2794. if (mfd->overlay_play_enable == 0) /* nothing to do */
  2795. return 0;
  2796. ret = copy_from_user(&req, argp, sizeof(req));
  2797. if (ret) {
  2798. printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n",
  2799. __func__);
  2800. return ret;
  2801. }
  2802. complete(&mfd->msmfb_update_notify);
  2803. mutex_lock(&msm_fb_notify_update_sem);
  2804. if (mfd->msmfb_no_update_notify_timer.function)
  2805. del_timer(&mfd->msmfb_no_update_notify_timer);
  2806. mfd->msmfb_no_update_notify_timer.expires = jiffies + (2 * HZ);
  2807. add_timer(&mfd->msmfb_no_update_notify_timer);
  2808. mutex_unlock(&msm_fb_notify_update_sem);
  2809. if (info->node == 0 && !(mfd->cont_splash_done)) { /* primary */
  2810. mdp_set_dma_pan_info(info, NULL, TRUE);
  2811. if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) {
  2812. pr_err("%s: can't turn on display!\n", __func__);
  2813. return -EINVAL;
  2814. }
  2815. }
  2816. ret = mdp4_overlay_play(info, &req);
  2817. if (unset_bl_level && !bl_updated)
  2818. schedule_delayed_work(&mfd->backlight_worker,
  2819. backlight_duration);
  2820. if (info->node == 0 && (mfd->cont_splash_done)) /* primary */
  2821. mdp_free_splash_buffer(mfd);
  2822. return ret;
  2823. }
  2824. static int msmfb_overlay_play_enable(struct fb_info *info, unsigned long *argp)
  2825. {
  2826. int ret, enable;
  2827. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  2828. ret = copy_from_user(&enable, argp, sizeof(enable));
  2829. if (ret) {
  2830. printk(KERN_ERR "%s:msmfb_overlay_play_enable ioctl failed \n",
  2831. __func__);
  2832. return ret;
  2833. }
  2834. mfd->overlay_play_enable = enable;
  2835. return 0;
  2836. }
  2837. static int msmfb_overlay_blt(struct fb_info *info, unsigned long *argp)
  2838. {
  2839. int ret;
  2840. struct msmfb_overlay_blt req;
  2841. ret = copy_from_user(&req, argp, sizeof(req));
  2842. if (ret) {
  2843. pr_err("%s: failed\n", __func__);
  2844. return ret;
  2845. }
  2846. ret = mdp4_overlay_blt(info, &req);
  2847. return ret;
  2848. }
  2849. #ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
  2850. static int msmfb_overlay_ioctl_writeback_init(struct fb_info *info)
  2851. {
  2852. return mdp4_writeback_init(info);
  2853. }
  2854. static int msmfb_overlay_ioctl_writeback_start(
  2855. struct fb_info *info)
  2856. {
  2857. int ret = 0;
  2858. ret = mdp4_writeback_start(info);
  2859. if (ret)
  2860. goto error;
  2861. error:
  2862. if (ret)
  2863. pr_err("%s:msmfb_writeback_start "
  2864. " ioctl failed\n", __func__);
  2865. return ret;
  2866. }
  2867. static int msmfb_overlay_ioctl_writeback_stop(
  2868. struct fb_info *info)
  2869. {
  2870. int ret = 0;
  2871. ret = mdp4_writeback_stop(info);
  2872. if (ret)
  2873. goto error;
  2874. error:
  2875. if (ret)
  2876. pr_err("%s:msmfb_writeback_stop ioctl failed\n",
  2877. __func__);
  2878. return ret;
  2879. }
  2880. static int msmfb_overlay_ioctl_writeback_queue_buffer(
  2881. struct fb_info *info, unsigned long *argp)
  2882. {
  2883. int ret = 0;
  2884. struct msmfb_data data;
  2885. ret = copy_from_user(&data, argp, sizeof(data));
  2886. if (ret)
  2887. goto error;
  2888. ret = mdp4_writeback_queue_buffer(info, &data);
  2889. if (ret)
  2890. goto error;
  2891. error:
  2892. if (ret)
  2893. pr_err("%s:msmfb_writeback_queue_buffer ioctl failed\n",
  2894. __func__);
  2895. return ret;
  2896. }
  2897. static int msmfb_overlay_ioctl_writeback_dequeue_buffer(
  2898. struct fb_info *info, unsigned long *argp)
  2899. {
  2900. int ret = 0;
  2901. struct msmfb_data data;
  2902. ret = copy_from_user(&data, argp, sizeof(data));
  2903. if (ret)
  2904. goto error;
  2905. ret = mdp4_writeback_dequeue_buffer(info, &data);
  2906. if (ret)
  2907. goto error;
  2908. ret = copy_to_user(argp, &data, sizeof(data));
  2909. if (ret)
  2910. goto error;
  2911. error:
  2912. if (ret)
  2913. pr_err("%s:msmfb_writeback_dequeue_buffer ioctl failed\n",
  2914. __func__);
  2915. return ret;
  2916. }
  2917. static int msmfb_overlay_ioctl_writeback_terminate(struct fb_info *info)
  2918. {
  2919. return mdp4_writeback_terminate(info);
  2920. }
  2921. static int msmfb_overlay_ioctl_writeback_set_mirr_hint(struct fb_info *
  2922. info, void *argp)
  2923. {
  2924. int ret = 0, hint;
  2925. if (!info) {
  2926. ret = -EINVAL;
  2927. goto error;
  2928. }
  2929. ret = copy_from_user(&hint, argp, sizeof(hint));
  2930. if (ret)
  2931. goto error;
  2932. ret = mdp4_writeback_set_mirroring_hint(info, hint);
  2933. if (ret)
  2934. goto error;
  2935. error:
  2936. if (ret)
  2937. pr_err("%s: ioctl failed\n", __func__);
  2938. return ret;
  2939. }
  2940. #else
  2941. static int msmfb_overlay_ioctl_writeback_init(struct fb_info *info)
  2942. {
  2943. return -ENOTSUPP;
  2944. }
  2945. static int msmfb_overlay_ioctl_writeback_start(
  2946. struct fb_info *info)
  2947. {
  2948. return -ENOTSUPP;
  2949. }
  2950. static int msmfb_overlay_ioctl_writeback_stop(
  2951. struct fb_info *info)
  2952. {
  2953. return -ENOTSUPP;
  2954. }
  2955. static int msmfb_overlay_ioctl_writeback_queue_buffer(
  2956. struct fb_info *info, unsigned long *argp)
  2957. {
  2958. return -ENOTSUPP;
  2959. }
  2960. static int msmfb_overlay_ioctl_writeback_dequeue_buffer(
  2961. struct fb_info *info, unsigned long *argp)
  2962. {
  2963. return -ENOTSUPP;
  2964. }
  2965. static int msmfb_overlay_ioctl_writeback_terminate(struct fb_info *info)
  2966. {
  2967. return -ENOTSUPP;
  2968. }
  2969. static int msmfb_overlay_ioctl_writeback_set_mirr_hint(struct fb_info *
  2970. info, void *argp)
  2971. {
  2972. return -ENOTSUPP;
  2973. }
  2974. #endif
  2975. static int msmfb_overlay_3d_sbys(struct fb_info *info, unsigned long *argp)
  2976. {
  2977. int ret;
  2978. struct msmfb_overlay_3d req;
  2979. ret = copy_from_user(&req, argp, sizeof(req));
  2980. if (ret) {
  2981. pr_err("%s:msmfb_overlay_3d_ctrl ioctl failed\n",
  2982. __func__);
  2983. return ret;
  2984. }
  2985. ret = mdp4_overlay_3d_sbys(info, &req);
  2986. return ret;
  2987. }
  2988. static int msmfb_mixer_info(struct fb_info *info, unsigned long *argp)
  2989. {
  2990. int ret, cnt;
  2991. struct msmfb_mixer_info_req req;
  2992. ret = copy_from_user(&req, argp, sizeof(req));
  2993. if (ret) {
  2994. pr_err("%s: failed\n", __func__);
  2995. return ret;
  2996. }
  2997. cnt = mdp4_mixer_info(req.mixer_num, req.info);
  2998. req.cnt = cnt;
  2999. ret = copy_to_user(argp, &req, sizeof(req));
  3000. if (ret)
  3001. pr_err("%s:msmfb_overlay_blt_off ioctl failed\n",
  3002. __func__);
  3003. return cnt;
  3004. }
  3005. #endif
  3006. DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem);
  3007. DEFINE_SEMAPHORE(msm_fb_ioctl_vsync_sem);
  3008. DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
  3009. /* Set color conversion matrix from user space */
  3010. #ifndef CONFIG_FB_MSM_MDP40
  3011. static void msmfb_set_color_conv(struct mdp_ccs *p)
  3012. {
  3013. int i;
  3014. if (p->direction == MDP_CCS_RGB2YUV) {
  3015. /* MDP cmd block enable */
  3016. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  3017. /* RGB->YUV primary forward matrix */
  3018. for (i = 0; i < MDP_CCS_SIZE; i++)
  3019. writel(p->ccs[i], MDP_CSC_PFMVn(i));
  3020. #ifdef CONFIG_FB_MSM_MDP31
  3021. for (i = 0; i < MDP_BV_SIZE; i++)
  3022. writel(p->bv[i], MDP_CSC_POST_BV2n(i));
  3023. #endif
  3024. /* MDP cmd block disable */
  3025. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  3026. } else {
  3027. /* MDP cmd block enable */
  3028. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  3029. /* YUV->RGB primary reverse matrix */
  3030. for (i = 0; i < MDP_CCS_SIZE; i++)
  3031. writel(p->ccs[i], MDP_CSC_PRMVn(i));
  3032. for (i = 0; i < MDP_BV_SIZE; i++)
  3033. writel(p->bv[i], MDP_CSC_PRE_BV1n(i));
  3034. /* MDP cmd block disable */
  3035. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
  3036. }
  3037. }
  3038. #else
  3039. static void msmfb_set_color_conv(struct mdp_csc *p)
  3040. {
  3041. mdp4_vg_csc_update(p);
  3042. }
  3043. #endif
  3044. static int msmfb_notify_update(struct fb_info *info, unsigned long *argp)
  3045. {
  3046. int ret, notify;
  3047. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  3048. ret = copy_from_user(&notify, argp, sizeof(int));
  3049. if (ret) {
  3050. pr_err("%s:ioctl failed\n", __func__);
  3051. return ret;
  3052. }
  3053. if (notify > NOTIFY_UPDATE_STOP)
  3054. return -EINVAL;
  3055. if (notify == NOTIFY_UPDATE_START) {
  3056. INIT_COMPLETION(mfd->msmfb_update_notify);
  3057. ret = wait_for_completion_interruptible_timeout(
  3058. &mfd->msmfb_update_notify, 4*HZ);
  3059. } else {
  3060. INIT_COMPLETION(mfd->msmfb_no_update_notify);
  3061. ret = wait_for_completion_interruptible_timeout(
  3062. &mfd->msmfb_no_update_notify, 4*HZ);
  3063. }
  3064. if (ret == 0)
  3065. ret = -ETIMEDOUT;
  3066. return (ret > 0) ? 0 : ret;
  3067. }
  3068. static int msmfb_handle_pp_ioctl(struct msm_fb_data_type *mfd,
  3069. struct msmfb_mdp_pp *pp_ptr)
  3070. {
  3071. int ret = -1;
  3072. #ifdef CONFIG_FB_MSM_MDP40
  3073. int i = 0;
  3074. #endif
  3075. if (!pp_ptr)
  3076. return ret;
  3077. switch (pp_ptr->op) {
  3078. #ifdef CONFIG_FB_MSM_MDP40
  3079. case mdp_op_csc_cfg:
  3080. ret = mdp4_csc_config(&(pp_ptr->data.csc_cfg_data));
  3081. for (i = 0; i < CSC_MAX_BLOCKS; i++) {
  3082. if (pp_ptr->data.csc_cfg_data.block ==
  3083. csc_cfg_matrix[i].block) {
  3084. memcpy(&csc_cfg_matrix[i].csc_data,
  3085. &(pp_ptr->data.csc_cfg_data.csc_data),
  3086. sizeof(struct mdp_csc_cfg));
  3087. break;
  3088. }
  3089. }
  3090. break;
  3091. case mdp_op_pcc_cfg:
  3092. ret = mdp4_pcc_cfg(&(pp_ptr->data.pcc_cfg_data));
  3093. break;
  3094. case mdp_op_lut_cfg:
  3095. switch (pp_ptr->data.lut_cfg_data.lut_type) {
  3096. case mdp_lut_igc:
  3097. ret = mdp4_igc_lut_config(
  3098. (struct mdp_igc_lut_data *)
  3099. &pp_ptr->data.lut_cfg_data.data);
  3100. break;
  3101. case mdp_lut_pgc:
  3102. ret = mdp4_argc_cfg(
  3103. &pp_ptr->data.lut_cfg_data.data.pgc_lut_data);
  3104. break;
  3105. case mdp_lut_hist:
  3106. ret = mdp_hist_lut_config(
  3107. (struct mdp_hist_lut_data *)
  3108. &pp_ptr->data.lut_cfg_data.data);
  3109. break;
  3110. default:
  3111. break;
  3112. }
  3113. break;
  3114. case mdp_op_qseed_cfg:
  3115. ret = mdp4_qseed_cfg((struct mdp_qseed_cfg_data *)
  3116. &pp_ptr->data.qseed_cfg_data);
  3117. break;
  3118. case mdp_op_calib_cfg:
  3119. ret = mdp4_calib_config((struct mdp_calib_config_data *)
  3120. &pp_ptr->data.calib_cfg);
  3121. break;
  3122. #endif
  3123. case mdp_bl_scale_cfg:
  3124. ret = mdp_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
  3125. &pp_ptr->data.bl_scale_data);
  3126. break;
  3127. default:
  3128. pr_warn("Unsupported request to MDP_PP IOCTL.\n");
  3129. ret = -EINVAL;
  3130. break;
  3131. }
  3132. return ret;
  3133. }
  3134. static int msmfb_handle_metadata_ioctl(struct msm_fb_data_type *mfd,
  3135. struct msmfb_metadata *metadata_ptr)
  3136. {
  3137. int ret;
  3138. switch (metadata_ptr->op) {
  3139. #ifdef CONFIG_FB_MSM_MDP40
  3140. case metadata_op_base_blend:
  3141. ret = mdp4_update_base_blend(mfd,
  3142. &metadata_ptr->data.blend_cfg);
  3143. break;
  3144. case metadata_op_wb_format:
  3145. ret = mdp4_update_writeback_format(mfd,
  3146. &metadata_ptr->data.mixer_cfg);
  3147. break;
  3148. #endif
  3149. default:
  3150. pr_warn("Unsupported request to MDP META IOCTL.\n");
  3151. ret = -EINVAL;
  3152. break;
  3153. }
  3154. return ret;
  3155. }
  3156. static int msmfb_get_metadata(struct msm_fb_data_type *mfd,
  3157. struct msmfb_metadata *metadata_ptr)
  3158. {
  3159. int ret = 0;
  3160. switch (metadata_ptr->op) {
  3161. case metadata_op_frame_rate:
  3162. metadata_ptr->data.panel_frame_rate =
  3163. mdp_get_panel_framerate(mfd);
  3164. break;
  3165. default:
  3166. pr_warn("Unsupported request to MDP META IOCTL.\n");
  3167. ret = -EINVAL;
  3168. break;
  3169. }
  3170. return ret;
  3171. }
  3172. static int msmfb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
  3173. struct mdp_buf_sync *buf_sync)
  3174. {
  3175. int i, fence_cnt = 0, ret = 0;
  3176. int acq_fen_fd[MDP_MAX_FENCE_FD];
  3177. struct sync_fence *fence;
  3178. if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
  3179. (mfd->timeline == NULL))
  3180. return -EINVAL;
  3181. if (buf_sync->acq_fen_fd_cnt)
  3182. ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
  3183. buf_sync->acq_fen_fd_cnt * sizeof(int));
  3184. if (ret) {
  3185. pr_err("%s:copy_from_user failed", __func__);
  3186. return ret;
  3187. }
  3188. mutex_lock(&mfd->sync_mutex);
  3189. for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
  3190. fence = sync_fence_fdget(acq_fen_fd[i]);
  3191. if (fence == NULL) {
  3192. pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
  3193. acq_fen_fd[i]);
  3194. ret = -EINVAL;
  3195. break;
  3196. }
  3197. mfd->acq_fen[i] = fence;
  3198. }
  3199. fence_cnt = i;
  3200. if (ret)
  3201. goto buf_sync_err_1;
  3202. mfd->acq_fen_cnt = fence_cnt;
  3203. if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
  3204. msm_fb_wait_for_fence(mfd);
  3205. mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
  3206. mfd->timeline_value + 2);
  3207. if (mfd->cur_rel_sync_pt == NULL) {
  3208. pr_err("%s: cannot create sync point", __func__);
  3209. ret = -ENOMEM;
  3210. goto buf_sync_err_1;
  3211. }
  3212. /* create fence */
  3213. mfd->cur_rel_fence = sync_fence_create("mdp-fence",
  3214. mfd->cur_rel_sync_pt);
  3215. if (mfd->cur_rel_fence == NULL) {
  3216. sync_pt_free(mfd->cur_rel_sync_pt);
  3217. mfd->cur_rel_sync_pt = NULL;
  3218. pr_err("%s: cannot create fence", __func__);
  3219. ret = -ENOMEM;
  3220. goto buf_sync_err_1;
  3221. }
  3222. /* create fd */
  3223. mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
  3224. sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
  3225. ret = copy_to_user(buf_sync->rel_fen_fd,
  3226. &mfd->cur_rel_fen_fd, sizeof(int));
  3227. if (ret) {
  3228. pr_err("%s:copy_to_user failed", __func__);
  3229. goto buf_sync_err_2;
  3230. }
  3231. mutex_unlock(&mfd->sync_mutex);
  3232. return ret;
  3233. buf_sync_err_2:
  3234. sync_fence_put(mfd->cur_rel_fence);
  3235. put_unused_fd(mfd->cur_rel_fen_fd);
  3236. mfd->cur_rel_fence = NULL;
  3237. mfd->cur_rel_fen_fd = 0;
  3238. buf_sync_err_1:
  3239. for (i = 0; i < fence_cnt; i++)
  3240. sync_fence_put(mfd->acq_fen[i]);
  3241. mfd->acq_fen_cnt = 0;
  3242. mutex_unlock(&mfd->sync_mutex);
  3243. return ret;
  3244. }
  3245. static int buf_fence_process(struct msm_fb_data_type *mfd,
  3246. struct mdp_buf_fence *buf_fence)
  3247. {
  3248. int i, fence_cnt = 0, ret;
  3249. struct sync_fence *fence;
  3250. if ((buf_fence->acq_fen_fd_cnt == 0) ||
  3251. (buf_fence->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
  3252. (mfd->timeline == NULL))
  3253. return -EINVAL;
  3254. mutex_lock(&mfd->sync_mutex);
  3255. for (i = 0; i < buf_fence->acq_fen_fd_cnt; i++) {
  3256. fence = sync_fence_fdget(buf_fence->acq_fen_fd[i]);
  3257. if (fence == NULL) {
  3258. pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
  3259. buf_fence->acq_fen_fd[i]);
  3260. ret = -EINVAL;
  3261. break;
  3262. }
  3263. mfd->acq_fen[i] = fence;
  3264. }
  3265. fence_cnt = i;
  3266. if (ret)
  3267. goto buf_fence_err_1;
  3268. mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
  3269. mfd->timeline_value + 2);
  3270. if (mfd->cur_rel_sync_pt == NULL) {
  3271. pr_err("%s: cannot create sync point", __func__);
  3272. ret = -ENOMEM;
  3273. goto buf_fence_err_1;
  3274. }
  3275. /* create fence */
  3276. mfd->cur_rel_fence = sync_fence_create("mdp-fence",
  3277. mfd->cur_rel_sync_pt);
  3278. if (mfd->cur_rel_fence == NULL) {
  3279. sync_pt_free(mfd->cur_rel_sync_pt);
  3280. mfd->cur_rel_sync_pt = NULL;
  3281. pr_err("%s: cannot create fence", __func__);
  3282. ret = -ENOMEM;
  3283. goto buf_fence_err_1;
  3284. }
  3285. /* create fd */
  3286. mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
  3287. sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
  3288. buf_fence->rel_fen_fd[0] = mfd->cur_rel_fen_fd;
  3289. /* Only one released fd for now, -1 indicates an end */
  3290. buf_fence->rel_fen_fd[1] = -1;
  3291. mfd->acq_fen_cnt = buf_fence->acq_fen_fd_cnt;
  3292. mutex_unlock(&mfd->sync_mutex);
  3293. return ret;
  3294. buf_fence_err_1:
  3295. for (i = 0; i < fence_cnt; i++)
  3296. sync_fence_put(mfd->acq_fen[i]);
  3297. mfd->acq_fen_cnt = 0;
  3298. mutex_unlock(&mfd->sync_mutex);
  3299. return ret;
  3300. }
  3301. static int msmfb_display_commit(struct fb_info *info,
  3302. unsigned long *argp)
  3303. {
  3304. int ret;
  3305. u32 copy_back = FALSE;
  3306. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  3307. struct mdp_display_commit disp_commit;
  3308. struct mdp_buf_fence *buf_fence;
  3309. ret = copy_from_user(&disp_commit, argp,
  3310. sizeof(disp_commit));
  3311. if (ret) {
  3312. pr_err("%s:copy_from_user failed", __func__);
  3313. return ret;
  3314. }
  3315. buf_fence = &disp_commit.buf_fence;
  3316. if (buf_fence->acq_fen_fd_cnt > 0)
  3317. ret = buf_fence_process(mfd, buf_fence);
  3318. if ((!ret) && (buf_fence->rel_fen_fd[0] > 0))
  3319. copy_back = TRUE;
  3320. ret = msm_fb_pan_display_ex(&disp_commit.var,
  3321. info, disp_commit.wait_for_finish);
  3322. if (copy_back) {
  3323. ret = copy_to_user(argp,
  3324. &disp_commit, sizeof(disp_commit));
  3325. if (ret)
  3326. pr_err("%s:copy_to_user failed", __func__);
  3327. }
  3328. return ret;
  3329. }
  3330. static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd,
  3331. unsigned long arg)
  3332. {
  3333. struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
  3334. void __user *argp = (void __user *)arg;
  3335. struct fb_cursor cursor;
  3336. struct fb_cmap cmap;
  3337. struct mdp_histogram_data hist;
  3338. struct mdp_histogram_start_req hist_req;
  3339. uint32_t block;
  3340. #ifndef CONFIG_FB_MSM_MDP40
  3341. struct mdp_ccs ccs_matrix;
  3342. #else
  3343. struct mdp_csc csc_matrix;
  3344. #endif
  3345. struct mdp_page_protection fb_page_protection;
  3346. struct msmfb_mdp_pp mdp_pp;
  3347. struct msmfb_metadata mdp_metadata;
  3348. struct mdp_buf_sync buf_sync;
  3349. int ret = 0;
  3350. msm_fb_pan_idle(mfd);
  3351. switch (cmd) {
  3352. #ifdef CONFIG_FB_MSM_OVERLAY
  3353. case MSMFB_OVERLAY_GET:
  3354. ret = msmfb_overlay_get(info, argp);
  3355. break;
  3356. case MSMFB_OVERLAY_SET:
  3357. ret = msmfb_overlay_set(info, argp);
  3358. break;
  3359. case MSMFB_OVERLAY_UNSET:
  3360. ret = msmfb_overlay_unset(info, argp);
  3361. break;
  3362. case MSMFB_OVERLAY_COMMIT:
  3363. down(&msm_fb_ioctl_ppp_sem);
  3364. ret = msmfb_overlay_commit(info);
  3365. up(&msm_fb_ioctl_ppp_sem);
  3366. break;
  3367. case MSMFB_OVERLAY_PLAY:
  3368. ret = msmfb_overlay_play(info, argp);
  3369. break;
  3370. case MSMFB_OVERLAY_PLAY_ENABLE:
  3371. ret = msmfb_overlay_play_enable(info, argp);
  3372. break;
  3373. case MSMFB_OVERLAY_PLAY_WAIT:
  3374. ret = msmfb_overlay_play_wait(info, argp);
  3375. break;
  3376. case MSMFB_OVERLAY_BLT:
  3377. ret = msmfb_overlay_blt(info, argp);
  3378. break;
  3379. case MSMFB_OVERLAY_3D:
  3380. ret = msmfb_overlay_3d_sbys(info, argp);
  3381. break;
  3382. case MSMFB_MIXER_INFO:
  3383. ret = msmfb_mixer_info(info, argp);
  3384. break;
  3385. case MSMFB_WRITEBACK_INIT:
  3386. ret = msmfb_overlay_ioctl_writeback_init(info);
  3387. break;
  3388. case MSMFB_WRITEBACK_START:
  3389. ret = msmfb_overlay_ioctl_writeback_start(
  3390. info);
  3391. break;
  3392. case MSMFB_WRITEBACK_STOP:
  3393. ret = msmfb_overlay_ioctl_writeback_stop(
  3394. info);
  3395. break;
  3396. case MSMFB_WRITEBACK_QUEUE_BUFFER:
  3397. ret = msmfb_overlay_ioctl_writeback_queue_buffer(
  3398. info, argp);
  3399. break;
  3400. case MSMFB_WRITEBACK_DEQUEUE_BUFFER:
  3401. ret = msmfb_overlay_ioctl_writeback_dequeue_buffer(
  3402. info, argp);
  3403. break;
  3404. case MSMFB_WRITEBACK_TERMINATE:
  3405. ret = msmfb_overlay_ioctl_writeback_terminate(info);
  3406. break;
  3407. case MSMFB_WRITEBACK_SET_MIRRORING_HINT:
  3408. ret = msmfb_overlay_ioctl_writeback_set_mirr_hint(
  3409. info, argp);
  3410. break;
  3411. #endif
  3412. case MSMFB_VSYNC_CTRL:
  3413. case MSMFB_OVERLAY_VSYNC_CTRL:
  3414. down(&msm_fb_ioctl_vsync_sem);
  3415. if (mdp_rev >= MDP_REV_40)
  3416. ret = msmfb_overlay_vsync_ctrl(info, argp);
  3417. else
  3418. ret = msmfb_vsync_ctrl(info, argp);
  3419. up(&msm_fb_ioctl_vsync_sem);
  3420. break;
  3421. case MSMFB_BLIT:
  3422. down(&msm_fb_ioctl_ppp_sem);
  3423. ret = msmfb_blit(info, argp);
  3424. up(&msm_fb_ioctl_ppp_sem);
  3425. break;
  3426. /* Ioctl for setting ccs matrix from user space */
  3427. case MSMFB_SET_CCS_MATRIX:
  3428. #ifndef CONFIG_FB_MSM_MDP40
  3429. ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix));
  3430. if (ret) {
  3431. printk(KERN_ERR
  3432. "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n",
  3433. __func__);
  3434. return ret;
  3435. }
  3436. down(&msm_fb_ioctl_ppp_sem);
  3437. if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
  3438. mdp_ccs_rgb2yuv = ccs_matrix;
  3439. else
  3440. mdp_ccs_yuv2rgb = ccs_matrix;
  3441. msmfb_set_color_conv(&ccs_matrix) ;
  3442. up(&msm_fb_ioctl_ppp_sem);
  3443. #else
  3444. ret = copy_from_user(&csc_matrix, argp, sizeof(csc_matrix));
  3445. if (ret) {
  3446. pr_err("%s:MSMFB_SET_CSC_MATRIX ioctl failed\n",
  3447. __func__);
  3448. return ret;
  3449. }
  3450. down(&msm_fb_ioctl_ppp_sem);
  3451. msmfb_set_color_conv(&csc_matrix);
  3452. up(&msm_fb_ioctl_ppp_sem);
  3453. #endif
  3454. break;
  3455. /* Ioctl for getting ccs matrix to user space */
  3456. case MSMFB_GET_CCS_MATRIX:
  3457. #ifndef CONFIG_FB_MSM_MDP40
  3458. ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ;
  3459. if (ret) {
  3460. printk(KERN_ERR
  3461. "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
  3462. __func__);
  3463. return ret;
  3464. }
  3465. down(&msm_fb_ioctl_ppp_sem);
  3466. if (ccs_matrix.direction == MDP_CCS_RGB2YUV)
  3467. ccs_matrix = mdp_ccs_rgb2yuv;
  3468. else
  3469. ccs_matrix = mdp_ccs_yuv2rgb;
  3470. ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix));
  3471. if (ret) {
  3472. printk(KERN_ERR
  3473. "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n",
  3474. __func__);
  3475. return ret ;
  3476. }
  3477. up(&msm_fb_ioctl_ppp_sem);
  3478. #else
  3479. ret = -EINVAL;
  3480. #endif
  3481. break;
  3482. case MSMFB_GRP_DISP:
  3483. #ifdef CONFIG_FB_MSM_MDP22
  3484. {
  3485. unsigned long grp_id;
  3486. ret = copy_from_user(&grp_id, argp, sizeof(grp_id));
  3487. if (ret)
  3488. return ret;
  3489. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  3490. writel(grp_id, MDP_FULL_BYPASS_WORD43);
  3491. mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF,
  3492. FALSE);
  3493. break;
  3494. }
  3495. #else
  3496. return -EFAULT;
  3497. #endif
  3498. case MSMFB_SUSPEND_SW_REFRESHER:
  3499. if (!mfd->panel_power_on)
  3500. return -EPERM;
  3501. mfd->sw_refreshing_enable = FALSE;
  3502. ret = msm_fb_stop_sw_refresher(mfd);
  3503. break;
  3504. case MSMFB_RESUME_SW_REFRESHER:
  3505. if (!mfd->panel_power_on)
  3506. return -EPERM;
  3507. mfd->sw_refreshing_enable = TRUE;
  3508. ret = msm_fb_resume_sw_refresher(mfd);
  3509. break;
  3510. case MSMFB_CURSOR:
  3511. ret = copy_from_user(&cursor, argp, sizeof(cursor));
  3512. if (ret)
  3513. return ret;
  3514. ret = msm_fb_cursor(info, &cursor);
  3515. break;
  3516. case MSMFB_SET_LUT:
  3517. ret = copy_from_user(&cmap, argp, sizeof(cmap));
  3518. if (ret)
  3519. return ret;
  3520. mutex_lock(&msm_fb_ioctl_lut_sem);
  3521. ret = msm_fb_set_lut(&cmap, info);
  3522. mutex_unlock(&msm_fb_ioctl_lut_sem);
  3523. break;
  3524. case MSMFB_HISTOGRAM:
  3525. if (!mfd->panel_power_on)
  3526. return -EPERM;
  3527. if (!mfd->do_histogram)
  3528. return -ENODEV;
  3529. ret = copy_from_user(&hist, argp, sizeof(hist));
  3530. if (ret)
  3531. return ret;
  3532. ret = mfd->do_histogram(info, &hist);
  3533. break;
  3534. case MSMFB_HISTOGRAM_START:
  3535. if (!mfd->panel_power_on)
  3536. return -EPERM;
  3537. if (!mfd->start_histogram)
  3538. return -ENODEV;
  3539. ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
  3540. if (ret)
  3541. return ret;
  3542. ret = mfd->start_histogram(&hist_req);
  3543. break;
  3544. case MSMFB_HISTOGRAM_STOP:
  3545. if (!mfd->stop_histogram)
  3546. return -ENODEV;
  3547. ret = copy_from_user(&block, argp, sizeof(int));
  3548. if (ret)
  3549. return ret;
  3550. ret = mfd->stop_histogram(info, block);
  3551. break;
  3552. case MSMFB_GET_PAGE_PROTECTION:
  3553. fb_page_protection.page_protection
  3554. = mfd->mdp_fb_page_protection;
  3555. ret = copy_to_user(argp, &fb_page_protection,
  3556. sizeof(fb_page_protection));
  3557. if (ret)
  3558. return ret;
  3559. break;
  3560. case MSMFB_NOTIFY_UPDATE:
  3561. ret = msmfb_notify_update(info, argp);
  3562. break;
  3563. case MSMFB_SET_PAGE_PROTECTION:
  3564. #if defined CONFIG_ARCH_QSD8X50 || defined CONFIG_ARCH_MSM8X60
  3565. ret = copy_from_user(&fb_page_protection, argp,
  3566. sizeof(fb_page_protection));
  3567. if (ret)
  3568. return ret;
  3569. /* Validate the proposed page protection settings. */
  3570. switch (fb_page_protection.page_protection) {
  3571. case MDP_FB_PAGE_PROTECTION_NONCACHED:
  3572. case MDP_FB_PAGE_PROTECTION_WRITECOMBINE:
  3573. case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE:
  3574. /* Write-back cache (read allocate) */
  3575. case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE:
  3576. /* Write-back cache (write allocate) */
  3577. case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE:
  3578. mfd->mdp_fb_page_protection =
  3579. fb_page_protection.page_protection;
  3580. break;
  3581. default:
  3582. ret = -EINVAL;
  3583. break;
  3584. }
  3585. #else
  3586. /*
  3587. * Don't allow caching until 7k DMA cache operations are
  3588. * available.
  3589. */
  3590. ret = -EINVAL;
  3591. #endif
  3592. break;
  3593. case MSMFB_MDP_PP:
  3594. ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
  3595. if (ret)
  3596. return ret;
  3597. ret = msmfb_handle_pp_ioctl(mfd, &mdp_pp);
  3598. if (ret == 1)
  3599. ret = copy_to_user(argp, &mdp_pp, sizeof(mdp_pp));
  3600. break;
  3601. case MSMFB_BUFFER_SYNC:
  3602. ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
  3603. if (ret)
  3604. return ret;
  3605. ret = msmfb_handle_buf_sync_ioctl(mfd, &buf_sync);
  3606. if (!ret)
  3607. ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync));
  3608. break;
  3609. case MSMFB_METADATA_SET:
  3610. ret = copy_from_user(&mdp_metadata, argp, sizeof(mdp_metadata));
  3611. if (ret)
  3612. return ret;
  3613. ret = msmfb_handle_metadata_ioctl(mfd, &mdp_metadata);
  3614. case MSMFB_DISPLAY_COMMIT:
  3615. ret = msmfb_display_commit(info, argp);
  3616. break;
  3617. case MSMFB_METADATA_GET:
  3618. ret = copy_from_user(&mdp_metadata, argp, sizeof(mdp_metadata));
  3619. if (ret)
  3620. return ret;
  3621. ret = msmfb_get_metadata(mfd, &mdp_metadata);
  3622. if (!ret)
  3623. ret = copy_to_user(argp, &mdp_metadata,
  3624. sizeof(mdp_metadata));
  3625. break;
  3626. default:
  3627. MSM_FB_INFO("MDP: unknown ioctl (cmd=%x) received!\n", cmd);
  3628. ret = -EINVAL;
  3629. break;
  3630. }
  3631. return ret;
  3632. }
  3633. static int msm_fb_register_driver(void)
  3634. {
  3635. return platform_driver_register(&msm_fb_driver);
  3636. }
  3637. #ifdef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
  3638. struct fb_info *msm_fb_get_writeback_fb(void)
  3639. {
  3640. int c = 0;
  3641. for (c = 0; c < fbi_list_index; ++c) {
  3642. struct msm_fb_data_type *mfd;
  3643. mfd = (struct msm_fb_data_type *)fbi_list[c]->par;
  3644. if (mfd->panel.type == WRITEBACK_PANEL)
  3645. return fbi_list[c];
  3646. }
  3647. return NULL;
  3648. }
  3649. EXPORT_SYMBOL(msm_fb_get_writeback_fb);
  3650. int msm_fb_writeback_start(struct fb_info *info)
  3651. {
  3652. return mdp4_writeback_start(info);
  3653. }
  3654. EXPORT_SYMBOL(msm_fb_writeback_start);
  3655. int msm_fb_writeback_queue_buffer(struct fb_info *info,
  3656. struct msmfb_data *data)
  3657. {
  3658. return mdp4_writeback_queue_buffer(info, data);
  3659. }
  3660. EXPORT_SYMBOL(msm_fb_writeback_queue_buffer);
  3661. int msm_fb_writeback_dequeue_buffer(struct fb_info *info,
  3662. struct msmfb_data *data)
  3663. {
  3664. return mdp4_writeback_dequeue_buffer(info, data);
  3665. }
  3666. EXPORT_SYMBOL(msm_fb_writeback_dequeue_buffer);
  3667. int msm_fb_writeback_stop(struct fb_info *info)
  3668. {
  3669. return mdp4_writeback_stop(info);
  3670. }
  3671. EXPORT_SYMBOL(msm_fb_writeback_stop);
  3672. int msm_fb_writeback_init(struct fb_info *info)
  3673. {
  3674. return mdp4_writeback_init(info);
  3675. }
  3676. EXPORT_SYMBOL(msm_fb_writeback_init);
  3677. int msm_fb_writeback_terminate(struct fb_info *info)
  3678. {
  3679. return mdp4_writeback_terminate(info);
  3680. }
  3681. EXPORT_SYMBOL(msm_fb_writeback_terminate);
  3682. #endif
  3683. struct platform_device *msm_fb_add_device(struct platform_device *pdev)
  3684. {
  3685. struct msm_fb_panel_data *pdata;
  3686. struct platform_device *this_dev = NULL;
  3687. struct fb_info *fbi;
  3688. struct msm_fb_data_type *mfd = NULL;
  3689. u32 type, id, fb_num;
  3690. if (!pdev)
  3691. return NULL;
  3692. id = pdev->id;
  3693. pdata = pdev->dev.platform_data;
  3694. if (!pdata)
  3695. return NULL;
  3696. type = pdata->panel_info.type;
  3697. #if defined MSM_FB_NUM
  3698. /*
  3699. * over written fb_num which defined
  3700. * at panel_info
  3701. *
  3702. */
  3703. if (type == HDMI_PANEL || type == DTV_PANEL ||
  3704. type == TV_PANEL || type == WRITEBACK_PANEL) {
  3705. if (hdmi_prim_display)
  3706. pdata->panel_info.fb_num = 2;
  3707. else
  3708. pdata->panel_info.fb_num = 1;
  3709. }
  3710. else
  3711. pdata->panel_info.fb_num = MSM_FB_NUM;
  3712. MSM_FB_INFO("setting pdata->panel_info.fb_num to %d. type: %d\n",
  3713. pdata->panel_info.fb_num, type);
  3714. #endif
  3715. fb_num = pdata->panel_info.fb_num;
  3716. if (fb_num <= 0)
  3717. return NULL;
  3718. if (fbi_list_index >= MAX_FBI_LIST) {
  3719. printk(KERN_ERR "msm_fb: no more framebuffer info list!\n");
  3720. return NULL;
  3721. }
  3722. /*
  3723. * alloc panel device data
  3724. */
  3725. this_dev = msm_fb_device_alloc(pdata, type, id);
  3726. if (!this_dev) {
  3727. printk(KERN_ERR
  3728. "%s: msm_fb_device_alloc failed!\n", __func__);
  3729. return NULL;
  3730. }
  3731. /*
  3732. * alloc framebuffer info + par data
  3733. */
  3734. fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
  3735. if (fbi == NULL) {
  3736. platform_device_put(this_dev);
  3737. printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n");
  3738. return NULL;
  3739. }
  3740. mfd = (struct msm_fb_data_type *)fbi->par;
  3741. mfd->key = MFD_KEY;
  3742. mfd->fbi = fbi;
  3743. mfd->panel.type = type;
  3744. mfd->panel.id = id;
  3745. mfd->fb_page = fb_num;
  3746. mfd->index = fbi_list_index;
  3747. mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
  3748. mfd->iclient = iclient;
  3749. /* link to the latest pdev */
  3750. mfd->pdev = this_dev;
  3751. mfd_list[mfd_list_index++] = mfd;
  3752. fbi_list[fbi_list_index++] = fbi;
  3753. /*
  3754. * set driver data
  3755. */
  3756. platform_set_drvdata(this_dev, mfd);
  3757. if (platform_device_add(this_dev)) {
  3758. printk(KERN_ERR "msm_fb: platform_device_add failed!\n");
  3759. platform_device_put(this_dev);
  3760. framebuffer_release(fbi);
  3761. fbi_list_index--;
  3762. return NULL;
  3763. }
  3764. #ifdef CONFIG_SEC_DEBUG
  3765. if (fbi_list_index == 1) {
  3766. sec_getlog_supply_fbinfo((void *)(fbi->fix.smem_start),
  3767. ALIGN(fbi->var.xres, 32),
  3768. fbi->var.yres,
  3769. fbi->var.bits_per_pixel,
  3770. 2);
  3771. }
  3772. #endif
  3773. return this_dev;
  3774. }
  3775. EXPORT_SYMBOL(msm_fb_add_device);
  3776. #ifdef CONFIG_SEC_DEBUG_SUBSYS
  3777. void get_fbinfo(int fb_num, unsigned int *fb_paddr, unsigned int *xres,
  3778. unsigned int *yres, unsigned int *bpp,
  3779. unsigned char *roff, unsigned char *rlen,
  3780. unsigned char *goff, unsigned char *glen,
  3781. unsigned char *boff, unsigned char *blen,
  3782. unsigned char *aoff, unsigned char *alen)
  3783. {
  3784. struct fb_info *info;
  3785. if (fb_num >= MAX_FBI_LIST)
  3786. return;
  3787. info = fbi_list[fb_num];
  3788. if (!info)
  3789. return;
  3790. *fb_paddr = (unsigned int)info->fix.smem_start;
  3791. *xres = ALIGN(info->var.xres, 32);
  3792. *yres = info->var.yres;
  3793. *bpp = info->var.bits_per_pixel;
  3794. *roff = info->var.red.offset;
  3795. *rlen = info->var.red.length;
  3796. *goff = info->var.green.offset;
  3797. *glen = info->var.green.length;
  3798. *boff = info->var.blue.offset;
  3799. *blen = info->var.blue.length;
  3800. *aoff = info->var.transp.offset;
  3801. *alen = info->var.transp.length;
  3802. return;
  3803. }
  3804. #endif
  3805. int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num,
  3806. int subsys_id)
  3807. {
  3808. struct fb_info *info;
  3809. struct msm_fb_data_type *mfd;
  3810. if (fb_num > MAX_FBI_LIST ||
  3811. (subsys_id != DISPLAY_SUBSYSTEM_ID &&
  3812. subsys_id != ROTATOR_SUBSYSTEM_ID)) {
  3813. pr_err("%s(): Invalid parameters\n", __func__);
  3814. return -1;
  3815. }
  3816. info = fbi_list[fb_num];
  3817. if (!info) {
  3818. pr_err("%s(): info is NULL\n", __func__);
  3819. return -1;
  3820. }
  3821. mfd = (struct msm_fb_data_type *)info->par;
  3822. if (subsys_id == DISPLAY_SUBSYSTEM_ID) {
  3823. if (mfd->display_iova)
  3824. *start = mfd->display_iova;
  3825. else
  3826. *start = info->fix.smem_start;
  3827. } else {
  3828. if (mfd->rotator_iova)
  3829. *start = mfd->rotator_iova;
  3830. else
  3831. *start = info->fix.smem_start;
  3832. }
  3833. *len = info->fix.smem_len;
  3834. return 0;
  3835. }
  3836. EXPORT_SYMBOL(get_fb_phys_info);
  3837. int __init msm_fb_init(void)
  3838. {
  3839. int rc = -ENODEV;
  3840. if (msm_fb_register_driver())
  3841. return rc;
  3842. #ifdef MSM_FB_ENABLE_DBGFS
  3843. {
  3844. struct dentry *root;
  3845. if ((root = msm_fb_get_debugfs_root()) != NULL) {
  3846. msm_fb_debugfs_file_create(root,
  3847. "msm_fb_msg_printing_level",
  3848. (u32 *) &msm_fb_msg_level);
  3849. msm_fb_debugfs_file_create(root,
  3850. "mddi_msg_printing_level",
  3851. (u32 *) &mddi_msg_level);
  3852. msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled",
  3853. (u32 *) &msm_fb_debug_enabled);
  3854. }
  3855. }
  3856. #endif
  3857. return 0;
  3858. }
  3859. /* Called by v4l2 driver to enable/disable overlay pipe */
  3860. int msm_fb_v4l2_enable(struct mdp_overlay *req, bool enable, void **par)
  3861. {
  3862. int err = 0;
  3863. #ifdef CONFIG_FB_MSM_MDP40
  3864. struct mdp4_overlay_pipe *pipe;
  3865. if (enable) {
  3866. err = mdp4_v4l2_overlay_set(fbi_list[0], req, &pipe);
  3867. *(struct mdp4_overlay_pipe **)par = pipe;
  3868. } else {
  3869. pipe = *(struct mdp4_overlay_pipe **)par;
  3870. mdp4_v4l2_overlay_clear(pipe);
  3871. }
  3872. #else
  3873. #ifdef CONFIG_FB_MSM_MDP30
  3874. if (enable)
  3875. err = mdp_ppp_v4l2_overlay_set(fbi_list[0], req);
  3876. else
  3877. err = mdp_ppp_v4l2_overlay_clear();
  3878. #else
  3879. err = -EINVAL;
  3880. #endif
  3881. #endif
  3882. return err;
  3883. }
  3884. EXPORT_SYMBOL(msm_fb_v4l2_enable);
  3885. /* Called by v4l2 driver to provide a frame for display */
  3886. int msm_fb_v4l2_update(void *par, bool bUserPtr,
  3887. unsigned long srcp0_addr, unsigned long srcp0_size,
  3888. unsigned long srcp1_addr, unsigned long srcp1_size,
  3889. unsigned long srcp2_addr, unsigned long srcp2_size)
  3890. {
  3891. #ifdef CONFIG_FB_MSM_MDP40
  3892. struct mdp4_overlay_pipe *pipe = (struct mdp4_overlay_pipe *)par;
  3893. return mdp4_v4l2_overlay_play(fbi_list[0], pipe,
  3894. srcp0_addr, srcp1_addr,
  3895. srcp2_addr);
  3896. #else
  3897. #ifdef CONFIG_FB_MSM_MDP30
  3898. if (bUserPtr)
  3899. return mdp_ppp_v4l2_overlay_play(fbi_list[0], true,
  3900. srcp0_addr, srcp0_size,
  3901. srcp1_addr, srcp1_size);
  3902. else
  3903. return mdp_ppp_v4l2_overlay_play(fbi_list[0], false,
  3904. srcp0_addr, srcp0_size,
  3905. srcp1_addr, srcp1_size);
  3906. #else
  3907. return -EINVAL;
  3908. #endif
  3909. #endif
  3910. }
  3911. EXPORT_SYMBOL(msm_fb_v4l2_update);
  3912. module_init(msm_fb_init);