0027-bcm2835-add-v4l2-camera-device.patch 172 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935
  1. From 19c1ada1c282d61163b6a24a6ee53517caec094c Mon Sep 17 00:00:00 2001
  2. From: Vincent Sanders <vincent.sanders@collabora.co.uk>
  3. Date: Wed, 30 Jan 2013 12:45:18 +0000
  4. Subject: [PATCH 027/114] bcm2835: add v4l2 camera device
  5. - Supports raw YUV capture, preview, JPEG and H264.
  6. - Uses videobuf2 for data transfer, using dma_buf.
  7. - Uses 3.6.10 timestamping
  8. - Camera power based on use
  9. - Uses immutable input mode on video encoder
  10. Signed-off-by: Daniel Stone <daniels@collabora.com>
  11. Signed-off-by: Luke Diamand <luked@broadcom.com>
  12. ---
  13. Documentation/video4linux/bcm2835-v4l2.txt | 60 +
  14. drivers/media/platform/Kconfig | 1 +
  15. drivers/media/platform/Makefile | 2 +
  16. drivers/media/platform/bcm2835/Kconfig | 25 +
  17. drivers/media/platform/bcm2835/Makefile | 5 +
  18. drivers/media/platform/bcm2835/bcm2835-camera.c | 1476 +++++++++++++++++
  19. drivers/media/platform/bcm2835/bcm2835-camera.h | 113 ++
  20. drivers/media/platform/bcm2835/controls.c | 725 ++++++++
  21. drivers/media/platform/bcm2835/mmal-common.h | 51 +
  22. drivers/media/platform/bcm2835/mmal-encodings.h | 93 ++
  23. drivers/media/platform/bcm2835/mmal-msg-common.h | 50 +
  24. drivers/media/platform/bcm2835/mmal-msg-format.h | 81 +
  25. drivers/media/platform/bcm2835/mmal-msg-port.h | 107 ++
  26. drivers/media/platform/bcm2835/mmal-msg.h | 404 +++++
  27. drivers/media/platform/bcm2835/mmal-parameters.h | 539 ++++++
  28. drivers/media/platform/bcm2835/mmal-vchiq.c | 1916 ++++++++++++++++++++++
  29. drivers/media/platform/bcm2835/mmal-vchiq.h | 178 ++
  30. 17 files changed, 5826 insertions(+)
  31. create mode 100644 Documentation/video4linux/bcm2835-v4l2.txt
  32. create mode 100644 drivers/media/platform/bcm2835/Kconfig
  33. create mode 100644 drivers/media/platform/bcm2835/Makefile
  34. create mode 100644 drivers/media/platform/bcm2835/bcm2835-camera.c
  35. create mode 100644 drivers/media/platform/bcm2835/bcm2835-camera.h
  36. create mode 100644 drivers/media/platform/bcm2835/controls.c
  37. create mode 100644 drivers/media/platform/bcm2835/mmal-common.h
  38. create mode 100644 drivers/media/platform/bcm2835/mmal-encodings.h
  39. create mode 100644 drivers/media/platform/bcm2835/mmal-msg-common.h
  40. create mode 100644 drivers/media/platform/bcm2835/mmal-msg-format.h
  41. create mode 100644 drivers/media/platform/bcm2835/mmal-msg-port.h
  42. create mode 100644 drivers/media/platform/bcm2835/mmal-msg.h
  43. create mode 100644 drivers/media/platform/bcm2835/mmal-parameters.h
  44. create mode 100644 drivers/media/platform/bcm2835/mmal-vchiq.c
  45. create mode 100644 drivers/media/platform/bcm2835/mmal-vchiq.h
  46. --- /dev/null
  47. +++ b/Documentation/video4linux/bcm2835-v4l2.txt
  48. @@ -0,0 +1,60 @@
  49. +
  50. +BCM2835 (aka Raspberry Pi) V4L2 driver
  51. +======================================
  52. +
  53. +1. Copyright
  54. +============
  55. +
  56. +Copyright © 2013 Raspberry Pi (Trading) Ltd.
  57. +
  58. +2. License
  59. +==========
  60. +
  61. +This program is free software; you can redistribute it and/or modify
  62. +it under the terms of the GNU General Public License as published by
  63. +the Free Software Foundation; either version 2 of the License, or
  64. +(at your option) any later version.
  65. +
  66. +This program is distributed in the hope that it will be useful,
  67. +but WITHOUT ANY WARRANTY; without even the implied warranty of
  68. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  69. +GNU General Public License for more details.
  70. +
  71. +You should have received a copy of the GNU General Public License
  72. +along with this program; if not, write to the Free Software
  73. +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  74. +
  75. +3. Quick Start
  76. +==============
  77. +
  78. +You need a version 1.0 or later of v4l2-ctl, available from:
  79. + git://git.linuxtv.org/v4l-utils.git
  80. +
  81. +$ sudo modprobe bcm2835-v4l2
  82. +
  83. +Turn on the overlay:
  84. +
  85. +$ v4l2-ctl --overlay=1
  86. +
  87. +Turn off the overlay:
  88. +
  89. +$ v4l2-ctl --overlay=0
  90. +
  91. +Set the capture format for video:
  92. +
  93. +$ v4l2-ctl --set-fmt-video=width=1920,height=1088,pixelformat=4
  94. +
  95. +(Note: 1088 not 1080).
  96. +
  97. +Capture:
  98. +
  99. +$ v4l2-ctl --stream-mmap=3 --stream-count=100 --stream-to=somefile.h264
  100. +
  101. +Stills capture:
  102. +
  103. +$ v4l2-ctl --set-fmt-video=width=2592,height=1944,pixelformat=3
  104. +$ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=somefile.jpg
  105. +
  106. +List of available formats:
  107. +
  108. +$ v4l2-ctl --list-formats
  109. --- a/drivers/media/platform/Kconfig
  110. +++ b/drivers/media/platform/Kconfig
  111. @@ -124,6 +124,7 @@ config VIDEO_S3C_CAMIF
  112. source "drivers/media/platform/soc_camera/Kconfig"
  113. source "drivers/media/platform/exynos4-is/Kconfig"
  114. source "drivers/media/platform/s5p-tv/Kconfig"
  115. +source "drivers/media/platform/bcm2835/Kconfig"
  116. endif # V4L_PLATFORM_DRIVERS
  117. --- a/drivers/media/platform/Makefile
  118. +++ b/drivers/media/platform/Makefile
  119. @@ -49,4 +49,6 @@ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1
  120. obj-y += omap/
  121. +obj-$(CONFIG_VIDEO_BCM2835) += bcm2835/
  122. +
  123. ccflags-y += -I$(srctree)/drivers/media/i2c
  124. --- /dev/null
  125. +++ b/drivers/media/platform/bcm2835/Kconfig
  126. @@ -0,0 +1,25 @@
  127. +# Broadcom VideoCore IV v4l2 camera support
  128. +
  129. +config VIDEO_BCM2835
  130. + bool "Broadcom BCM2835 camera interface driver"
  131. + depends on VIDEO_V4L2 && ARCH_BCM2708
  132. + ---help---
  133. + Say Y here to enable camera host interface devices for
  134. + Broadcom BCM2835 SoC. This operates over the VCHIQ interface
  135. + to a service running on VideoCore.
  136. +
  137. +
  138. +if VIDEO_BCM2835
  139. +
  140. +config VIDEO_BCM2835_MMAL
  141. + tristate "Broadcom BM2835 MMAL camera interface driver"
  142. + depends on BCM2708_VCHIQ
  143. + select VIDEOBUF2_VMALLOC
  144. + ---help---
  145. + This is a V4L2 driver for the Broadcom BCM2835 MMAL camera host interface
  146. +
  147. + To compile this driver as a module, choose M here: the
  148. + module will be called bcm2835-v4l2.o
  149. +
  150. +
  151. +endif # VIDEO_BM2835
  152. --- /dev/null
  153. +++ b/drivers/media/platform/bcm2835/Makefile
  154. @@ -0,0 +1,5 @@
  155. +bcm2835-v4l2-objs := bcm2835-camera.o controls.o mmal-vchiq.o
  156. +
  157. +obj-$(CONFIG_VIDEO_BCM2835_MMAL) += bcm2835-v4l2.o
  158. +
  159. +ccflags-$(CONFIG_VIDEO_BCM2835) += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000
  160. --- /dev/null
  161. +++ b/drivers/media/platform/bcm2835/bcm2835-camera.c
  162. @@ -0,0 +1,1476 @@
  163. +/*
  164. + * Broadcom BM2835 V4L2 driver
  165. + *
  166. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  167. + *
  168. + * This file is subject to the terms and conditions of the GNU General Public
  169. + * License. See the file COPYING in the main directory of this archive
  170. + * for more details.
  171. + *
  172. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  173. + * Dave Stevenson <dsteve@broadcom.com>
  174. + * Simon Mellor <simellor@broadcom.com>
  175. + * Luke Diamand <luked@broadcom.com>
  176. + */
  177. +
  178. +#include <linux/errno.h>
  179. +#include <linux/kernel.h>
  180. +#include <linux/module.h>
  181. +#include <linux/slab.h>
  182. +#include <media/videobuf2-vmalloc.h>
  183. +#include <media/videobuf2-dma-contig.h>
  184. +#include <media/v4l2-device.h>
  185. +#include <media/v4l2-ioctl.h>
  186. +#include <media/v4l2-ctrls.h>
  187. +#include <media/v4l2-fh.h>
  188. +#include <media/v4l2-event.h>
  189. +#include <media/v4l2-common.h>
  190. +#include <linux/delay.h>
  191. +
  192. +#include "mmal-common.h"
  193. +#include "mmal-encodings.h"
  194. +#include "mmal-vchiq.h"
  195. +#include "mmal-msg.h"
  196. +#include "mmal-parameters.h"
  197. +#include "bcm2835-camera.h"
  198. +
  199. +#define BM2835_MMAL_VERSION "0.0.2"
  200. +#define BM2835_MMAL_MODULE_NAME "bcm2835-v4l2"
  201. +
  202. +#define MAX_WIDTH 2592
  203. +#define MAX_HEIGHT 1944
  204. +#define MIN_BUFFER_SIZE (80*1024)
  205. +
  206. +#define MAX_VIDEO_MODE_WIDTH 1280
  207. +#define MAX_VIDEO_MODE_HEIGHT 720
  208. +
  209. +MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture");
  210. +MODULE_AUTHOR("Vincent Sanders");
  211. +MODULE_LICENSE("GPL");
  212. +MODULE_VERSION(BM2835_MMAL_VERSION);
  213. +
  214. +int bcm2835_v4l2_debug;
  215. +module_param_named(debug, bcm2835_v4l2_debug, int, 0644);
  216. +MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2");
  217. +
  218. +static struct bm2835_mmal_dev *gdev; /* global device data */
  219. +
  220. +/* video formats */
  221. +static struct mmal_fmt formats[] = {
  222. + {
  223. + .name = "4:2:0, packed YUV",
  224. + .fourcc = V4L2_PIX_FMT_YUV420,
  225. + .mmal = MMAL_ENCODING_I420,
  226. + .depth = 12,
  227. + .mmal_component = MMAL_COMPONENT_CAMERA,
  228. + },
  229. + {
  230. + .name = "4:2:2, packed, YUYV",
  231. + .fourcc = V4L2_PIX_FMT_YUYV,
  232. + .mmal = MMAL_ENCODING_YUYV,
  233. + .depth = 16,
  234. + .mmal_component = MMAL_COMPONENT_CAMERA,
  235. + },
  236. + {
  237. + .name = "RGB24 (BE)",
  238. + .fourcc = V4L2_PIX_FMT_BGR24,
  239. + .mmal = MMAL_ENCODING_BGR24,
  240. + .depth = 24,
  241. + .mmal_component = MMAL_COMPONENT_CAMERA,
  242. + },
  243. + {
  244. + .name = "JPEG",
  245. + .fourcc = V4L2_PIX_FMT_JPEG,
  246. + .mmal = MMAL_ENCODING_JPEG,
  247. + .depth = 8,
  248. + .mmal_component = MMAL_COMPONENT_IMAGE_ENCODE,
  249. + },
  250. + {
  251. + .name = "H264",
  252. + .fourcc = V4L2_PIX_FMT_H264,
  253. + .mmal = MMAL_ENCODING_H264,
  254. + .depth = 8,
  255. + .mmal_component = MMAL_COMPONENT_VIDEO_ENCODE,
  256. + }
  257. +};
  258. +
  259. +static struct mmal_fmt *get_format(struct v4l2_format *f)
  260. +{
  261. + struct mmal_fmt *fmt;
  262. + unsigned int k;
  263. +
  264. + for (k = 0; k < ARRAY_SIZE(formats); k++) {
  265. + fmt = &formats[k];
  266. + if (fmt->fourcc == f->fmt.pix.pixelformat)
  267. + break;
  268. + }
  269. +
  270. + if (k == ARRAY_SIZE(formats))
  271. + return NULL;
  272. +
  273. + return &formats[k];
  274. +}
  275. +
  276. +/* ------------------------------------------------------------------
  277. + Videobuf queue operations
  278. + ------------------------------------------------------------------*/
  279. +
  280. +static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
  281. + unsigned int *nbuffers, unsigned int *nplanes,
  282. + unsigned int sizes[], void *alloc_ctxs[])
  283. +{
  284. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
  285. + unsigned long size;
  286. +
  287. + /* refuse queue setup if port is not configured */
  288. + if (dev->capture.port == NULL) {
  289. + v4l2_err(&dev->v4l2_dev,
  290. + "%s: capture port not configured\n", __func__);
  291. + return -EINVAL;
  292. + }
  293. +
  294. + size = dev->capture.port->current_buffer.size;
  295. + if (size == 0) {
  296. + v4l2_err(&dev->v4l2_dev,
  297. + "%s: capture port buffer size is zero\n", __func__);
  298. + return -EINVAL;
  299. + }
  300. +
  301. + if (*nbuffers < (dev->capture.port->current_buffer.num + 2))
  302. + *nbuffers = (dev->capture.port->current_buffer.num + 2);
  303. +
  304. + *nplanes = 1;
  305. +
  306. + sizes[0] = size;
  307. +
  308. + /*
  309. + * videobuf2-vmalloc allocator is context-less so no need to set
  310. + * alloc_ctxs array.
  311. + */
  312. +
  313. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
  314. + __func__, dev);
  315. +
  316. + return 0;
  317. +}
  318. +
  319. +static int buffer_prepare(struct vb2_buffer *vb)
  320. +{
  321. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
  322. + unsigned long size;
  323. +
  324. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
  325. + __func__, dev);
  326. +
  327. + BUG_ON(dev->capture.port == NULL);
  328. + BUG_ON(dev->capture.fmt == NULL);
  329. +
  330. + size = dev->capture.stride * dev->capture.height;
  331. + if (vb2_plane_size(vb, 0) < size) {
  332. + v4l2_err(&dev->v4l2_dev,
  333. + "%s data will not fit into plane (%lu < %lu)\n",
  334. + __func__, vb2_plane_size(vb, 0), size);
  335. + return -EINVAL;
  336. + }
  337. +
  338. + return 0;
  339. +}
  340. +
  341. +static inline bool is_capturing(struct bm2835_mmal_dev *dev)
  342. +{
  343. + return dev->capture.camera_port ==
  344. + &dev->
  345. + component[MMAL_COMPONENT_CAMERA]->output[MMAL_CAMERA_PORT_CAPTURE];
  346. +}
  347. +
  348. +static void buffer_cb(struct vchiq_mmal_instance *instance,
  349. + struct vchiq_mmal_port *port,
  350. + int status,
  351. + struct mmal_buffer *buf,
  352. + unsigned long length, u32 mmal_flags, s64 dts, s64 pts)
  353. +{
  354. + struct bm2835_mmal_dev *dev = port->cb_ctx;
  355. +
  356. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  357. + "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n",
  358. + __func__, status, buf, length, mmal_flags, pts);
  359. +
  360. + if (status != 0) {
  361. + /* error in transfer */
  362. + if (buf != NULL) {
  363. + /* there was a buffer with the error so return it */
  364. + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
  365. + }
  366. + return;
  367. + } else if (length == 0) {
  368. + /* stream ended */
  369. + if (buf != NULL) {
  370. + /* this should only ever happen if the port is
  371. + * disabled and there are buffers still queued
  372. + */
  373. + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
  374. + pr_debug("Empty buffer");
  375. + } else if (dev->capture.frame_count) {
  376. + /* grab another frame */
  377. + if (is_capturing(dev)) {
  378. + pr_debug("Grab another frame");
  379. + vchiq_mmal_port_parameter_set(
  380. + instance,
  381. + dev->capture.
  382. + camera_port,
  383. + MMAL_PARAMETER_CAPTURE,
  384. + &dev->capture.
  385. + frame_count,
  386. + sizeof(dev->capture.frame_count));
  387. + }
  388. + } else {
  389. + /* signal frame completion */
  390. + complete(&dev->capture.frame_cmplt);
  391. + }
  392. + } else {
  393. + if (dev->capture.frame_count) {
  394. + if (dev->capture.vc_start_timestamp != -1) {
  395. + s64 runtime_us = pts -
  396. + dev->capture.vc_start_timestamp;
  397. + u32 div = 0;
  398. + u32 rem = 0;
  399. +
  400. + div =
  401. + div_u64_rem(runtime_us, USEC_PER_SEC, &rem);
  402. + buf->vb.v4l2_buf.timestamp.tv_sec =
  403. + dev->capture.kernel_start_ts.tv_sec - 1 +
  404. + div;
  405. + buf->vb.v4l2_buf.timestamp.tv_usec =
  406. + dev->capture.kernel_start_ts.tv_usec + rem;
  407. +
  408. + if (buf->vb.v4l2_buf.timestamp.tv_usec >=
  409. + USEC_PER_SEC) {
  410. + buf->vb.v4l2_buf.timestamp.tv_sec++;
  411. + buf->vb.v4l2_buf.timestamp.tv_usec -=
  412. + USEC_PER_SEC;
  413. + }
  414. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  415. + "Convert start time %d.%06d and %llu"
  416. + "with offset %llu to %d.%06d\n",
  417. + (int)dev->capture.kernel_start_ts.
  418. + tv_sec,
  419. + (int)dev->capture.kernel_start_ts.
  420. + tv_usec,
  421. + dev->capture.vc_start_timestamp, pts,
  422. + (int)buf->vb.v4l2_buf.timestamp.tv_sec,
  423. + (int)buf->vb.v4l2_buf.timestamp.
  424. + tv_usec);
  425. + } else {
  426. + v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
  427. + }
  428. +
  429. + vb2_set_plane_payload(&buf->vb, 0, length);
  430. + vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
  431. +
  432. + if (mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS &&
  433. + is_capturing(dev)) {
  434. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  435. + "Grab another frame as buffer has EOS");
  436. + vchiq_mmal_port_parameter_set(
  437. + instance,
  438. + dev->capture.
  439. + camera_port,
  440. + MMAL_PARAMETER_CAPTURE,
  441. + &dev->capture.
  442. + frame_count,
  443. + sizeof(dev->capture.frame_count));
  444. + }
  445. + } else {
  446. + /* signal frame completion */
  447. + complete(&dev->capture.frame_cmplt);
  448. + }
  449. + }
  450. +}
  451. +
  452. +static int enable_camera(struct bm2835_mmal_dev *dev)
  453. +{
  454. + int ret;
  455. + if (!dev->camera_use_count) {
  456. + ret = vchiq_mmal_component_enable(
  457. + dev->instance,
  458. + dev->component[MMAL_COMPONENT_CAMERA]);
  459. + if (ret < 0) {
  460. + v4l2_err(&dev->v4l2_dev,
  461. + "Failed enabling camera, ret %d\n", ret);
  462. + return -EINVAL;
  463. + }
  464. + }
  465. + dev->camera_use_count++;
  466. + v4l2_dbg(1, bcm2835_v4l2_debug,
  467. + &dev->v4l2_dev, "enabled camera (refcount %d)\n",
  468. + dev->camera_use_count);
  469. + return 0;
  470. +}
  471. +
  472. +static int disable_camera(struct bm2835_mmal_dev *dev)
  473. +{
  474. + int ret;
  475. + if (!dev->camera_use_count) {
  476. + v4l2_err(&dev->v4l2_dev,
  477. + "Disabled the camera when already disabled\n");
  478. + return -EINVAL;
  479. + }
  480. + dev->camera_use_count--;
  481. + if (!dev->camera_use_count) {
  482. + unsigned int i = 0xFFFFFFFF;
  483. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  484. + "Disabling camera\n");
  485. + ret =
  486. + vchiq_mmal_component_disable(
  487. + dev->instance,
  488. + dev->component[MMAL_COMPONENT_CAMERA]);
  489. + if (ret < 0) {
  490. + v4l2_err(&dev->v4l2_dev,
  491. + "Failed disabling camera, ret %d\n", ret);
  492. + return -EINVAL;
  493. + }
  494. + vchiq_mmal_port_parameter_set(
  495. + dev->instance,
  496. + &dev->component[MMAL_COMPONENT_CAMERA]->control,
  497. + MMAL_PARAMETER_CAMERA_NUM, &i,
  498. + sizeof(i));
  499. + }
  500. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  501. + "Camera refcount now %d\n", dev->camera_use_count);
  502. + return 0;
  503. +}
  504. +
  505. +static void buffer_queue(struct vb2_buffer *vb)
  506. +{
  507. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
  508. + struct mmal_buffer *buf = container_of(vb, struct mmal_buffer, vb);
  509. + int ret;
  510. +
  511. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  512. + "%s: dev:%p buf:%p\n", __func__, dev, buf);
  513. +
  514. + buf->buffer = vb2_plane_vaddr(&buf->vb, 0);
  515. + buf->buffer_size = vb2_plane_size(&buf->vb, 0);
  516. +
  517. + ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, buf);
  518. + if (ret < 0)
  519. + v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n",
  520. + __func__);
  521. +}
  522. +
  523. +static int start_streaming(struct vb2_queue *vq, unsigned int count)
  524. +{
  525. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
  526. + int ret;
  527. + int parameter_size;
  528. +
  529. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
  530. + __func__, dev);
  531. +
  532. + /* ensure a format has actually been set */
  533. + if (dev->capture.port == NULL)
  534. + return -EINVAL;
  535. +
  536. + if (enable_camera(dev) < 0) {
  537. + v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n");
  538. + return -EINVAL;
  539. + }
  540. +
  541. + /*init_completion(&dev->capture.frame_cmplt); */
  542. +
  543. + /* enable frame capture */
  544. + dev->capture.frame_count = 1;
  545. +
  546. + /* if the preview is not already running, wait for a few frames for AGC
  547. + * to settle down.
  548. + */
  549. + if (!dev->component[MMAL_COMPONENT_PREVIEW]->enabled)
  550. + msleep(300);
  551. +
  552. + /* enable the connection from camera to encoder (if applicable) */
  553. + if (dev->capture.camera_port != dev->capture.port
  554. + && dev->capture.camera_port) {
  555. + ret = vchiq_mmal_port_enable(dev->instance,
  556. + dev->capture.camera_port, NULL);
  557. + if (ret) {
  558. + v4l2_err(&dev->v4l2_dev,
  559. + "Failed to enable encode tunnel - error %d\n",
  560. + ret);
  561. + return -1;
  562. + }
  563. + }
  564. +
  565. + /* Get VC timestamp at this point in time */
  566. + parameter_size = sizeof(dev->capture.vc_start_timestamp);
  567. + if (vchiq_mmal_port_parameter_get(dev->instance,
  568. + dev->capture.camera_port,
  569. + MMAL_PARAMETER_SYSTEM_TIME,
  570. + &dev->capture.vc_start_timestamp,
  571. + &parameter_size)) {
  572. + v4l2_err(&dev->v4l2_dev,
  573. + "Failed to get VC start time - update your VC f/w\n");
  574. +
  575. + /* Flag to indicate just to rely on kernel timestamps */
  576. + dev->capture.vc_start_timestamp = -1;
  577. + } else
  578. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  579. + "Start time %lld size %d\n",
  580. + dev->capture.vc_start_timestamp, parameter_size);
  581. +
  582. + v4l2_get_timestamp(&dev->capture.kernel_start_ts);
  583. +
  584. + /* enable the camera port */
  585. + dev->capture.port->cb_ctx = dev;
  586. + ret =
  587. + vchiq_mmal_port_enable(dev->instance, dev->capture.port, buffer_cb);
  588. + if (ret) {
  589. + v4l2_err(&dev->v4l2_dev,
  590. + "Failed to enable capture port - error %d\n", ret);
  591. + return -1;
  592. + }
  593. +
  594. + /* capture the first frame */
  595. + vchiq_mmal_port_parameter_set(dev->instance,
  596. + dev->capture.camera_port,
  597. + MMAL_PARAMETER_CAPTURE,
  598. + &dev->capture.frame_count,
  599. + sizeof(dev->capture.frame_count));
  600. + return 0;
  601. +}
  602. +
  603. +/* abort streaming and wait for last buffer */
  604. +static int stop_streaming(struct vb2_queue *vq)
  605. +{
  606. + int ret;
  607. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
  608. +
  609. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n",
  610. + __func__, dev);
  611. +
  612. + init_completion(&dev->capture.frame_cmplt);
  613. + dev->capture.frame_count = 0;
  614. +
  615. + /* ensure a format has actually been set */
  616. + if (dev->capture.port == NULL)
  617. + return -EINVAL;
  618. +
  619. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n");
  620. +
  621. + /* stop capturing frames */
  622. + vchiq_mmal_port_parameter_set(dev->instance,
  623. + dev->capture.camera_port,
  624. + MMAL_PARAMETER_CAPTURE,
  625. + &dev->capture.frame_count,
  626. + sizeof(dev->capture.frame_count));
  627. +
  628. + /* wait for last frame to complete */
  629. + ret = wait_for_completion_timeout(&dev->capture.frame_cmplt, HZ);
  630. + if (ret <= 0)
  631. + v4l2_err(&dev->v4l2_dev,
  632. + "error %d waiting for frame completion\n", ret);
  633. +
  634. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  635. + "disabling connection\n");
  636. +
  637. + /* disable the connection from camera to encoder */
  638. + ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port);
  639. + if (!ret && dev->capture.camera_port != dev->capture.port) {
  640. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  641. + "disabling port\n");
  642. + ret = vchiq_mmal_port_disable(dev->instance, dev->capture.port);
  643. + } else if (dev->capture.camera_port != dev->capture.port) {
  644. + v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n",
  645. + ret);
  646. + }
  647. +
  648. + if (disable_camera(dev) < 0) {
  649. + v4l2_err(&dev->v4l2_dev, "Failed to disable camera");
  650. + return -EINVAL;
  651. + }
  652. +
  653. + return ret;
  654. +}
  655. +
  656. +static void bm2835_mmal_lock(struct vb2_queue *vq)
  657. +{
  658. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
  659. + mutex_lock(&dev->mutex);
  660. +}
  661. +
  662. +static void bm2835_mmal_unlock(struct vb2_queue *vq)
  663. +{
  664. + struct bm2835_mmal_dev *dev = vb2_get_drv_priv(vq);
  665. + mutex_unlock(&dev->mutex);
  666. +}
  667. +
  668. +static struct vb2_ops bm2835_mmal_video_qops = {
  669. + .queue_setup = queue_setup,
  670. + .buf_prepare = buffer_prepare,
  671. + .buf_queue = buffer_queue,
  672. + .start_streaming = start_streaming,
  673. + .stop_streaming = stop_streaming,
  674. + .wait_prepare = bm2835_mmal_unlock,
  675. + .wait_finish = bm2835_mmal_lock,
  676. +};
  677. +
  678. +/* ------------------------------------------------------------------
  679. + IOCTL operations
  680. + ------------------------------------------------------------------*/
  681. +
  682. +/* overlay ioctl */
  683. +static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv,
  684. + struct v4l2_fmtdesc *f)
  685. +{
  686. + struct mmal_fmt *fmt;
  687. +
  688. + if (f->index >= ARRAY_SIZE(formats))
  689. + return -EINVAL;
  690. +
  691. + fmt = &formats[f->index];
  692. +
  693. + strlcpy(f->description, fmt->name, sizeof(f->description));
  694. + f->pixelformat = fmt->fourcc;
  695. +
  696. + return 0;
  697. +}
  698. +
  699. +static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv,
  700. + struct v4l2_format *f)
  701. +{
  702. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  703. +
  704. + f->fmt.win = dev->overlay;
  705. +
  706. + return 0;
  707. +}
  708. +
  709. +static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv,
  710. + struct v4l2_format *f)
  711. +{
  712. + /* Only support one format so get the current one. */
  713. + vidioc_g_fmt_vid_overlay(file, priv, f);
  714. +
  715. + /* todo: allow the size and/or offset to be changed. */
  716. + return 0;
  717. +}
  718. +
  719. +static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv,
  720. + struct v4l2_format *f)
  721. +{
  722. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  723. +
  724. + vidioc_try_fmt_vid_overlay(file, priv, f);
  725. +
  726. + dev->overlay = f->fmt.win;
  727. +
  728. + /* todo: program the preview port parameters */
  729. + return 0;
  730. +}
  731. +
  732. +static int vidioc_overlay(struct file *file, void *f, unsigned int on)
  733. +{
  734. + int ret;
  735. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  736. + struct vchiq_mmal_port *src;
  737. + struct vchiq_mmal_port *dst;
  738. + struct mmal_parameter_displayregion prev_config = {
  739. + .set = MMAL_DISPLAY_SET_LAYER | MMAL_DISPLAY_SET_ALPHA |
  740. + MMAL_DISPLAY_SET_DEST_RECT | MMAL_DISPLAY_SET_FULLSCREEN,
  741. + .layer = PREVIEW_LAYER,
  742. + .alpha = 255,
  743. + .fullscreen = 0,
  744. + .dest_rect = {
  745. + .x = dev->overlay.w.left,
  746. + .y = dev->overlay.w.top,
  747. + .width = dev->overlay.w.width,
  748. + .height = dev->overlay.w.height,
  749. + },
  750. + };
  751. +
  752. + if ((on && dev->component[MMAL_COMPONENT_PREVIEW]->enabled) ||
  753. + (!on && !dev->component[MMAL_COMPONENT_PREVIEW]->enabled))
  754. + return 0; /* already in requested state */
  755. +
  756. + src =
  757. + &dev->component[MMAL_COMPONENT_CAMERA]->
  758. + output[MMAL_CAMERA_PORT_PREVIEW];
  759. +
  760. + if (!on) {
  761. + /* disconnect preview ports and disable component */
  762. + ret = vchiq_mmal_port_disable(dev->instance, src);
  763. + if (!ret)
  764. + ret =
  765. + vchiq_mmal_port_connect_tunnel(dev->instance, src,
  766. + NULL);
  767. + if (ret >= 0)
  768. + ret = vchiq_mmal_component_disable(
  769. + dev->instance,
  770. + dev->component[MMAL_COMPONENT_PREVIEW]);
  771. +
  772. + disable_camera(dev);
  773. + return ret;
  774. + }
  775. +
  776. + /* set preview port format and connect it to output */
  777. + dst = &dev->component[MMAL_COMPONENT_PREVIEW]->input[0];
  778. +
  779. + ret = vchiq_mmal_port_set_format(dev->instance, src);
  780. + if (ret < 0)
  781. + goto error;
  782. +
  783. + ret = vchiq_mmal_port_parameter_set(dev->instance, dst,
  784. + MMAL_PARAMETER_DISPLAYREGION,
  785. + &prev_config, sizeof(prev_config));
  786. + if (ret < 0)
  787. + goto error;
  788. +
  789. + if (enable_camera(dev) < 0)
  790. + goto error;
  791. +
  792. + ret = vchiq_mmal_component_enable(
  793. + dev->instance,
  794. + dev->component[MMAL_COMPONENT_PREVIEW]);
  795. + if (ret < 0)
  796. + goto error;
  797. +
  798. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n",
  799. + src, dst);
  800. + ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst);
  801. + if (!ret)
  802. + ret = vchiq_mmal_port_enable(dev->instance, src, NULL);
  803. +error:
  804. + return ret;
  805. +}
  806. +
  807. +static int vidioc_g_fbuf(struct file *file, void *fh,
  808. + struct v4l2_framebuffer *a)
  809. +{
  810. + /* The video overlay must stay within the framebuffer and can't be
  811. + positioned independently. */
  812. + a->flags = V4L2_FBUF_FLAG_OVERLAY;
  813. +
  814. + /* todo: v4l2_framebuffer still needs more info filling in
  815. + * in order to pass the v4l2-compliance test. */
  816. +
  817. + return 0;
  818. +}
  819. +
  820. +/* input ioctls */
  821. +static int vidioc_enum_input(struct file *file, void *priv,
  822. + struct v4l2_input *inp)
  823. +{
  824. + /* only a single camera input */
  825. + if (inp->index != 0)
  826. + return -EINVAL;
  827. +
  828. + inp->type = V4L2_INPUT_TYPE_CAMERA;
  829. + sprintf(inp->name, "Camera %u", inp->index);
  830. + return 0;
  831. +}
  832. +
  833. +static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
  834. +{
  835. + *i = 0;
  836. + return 0;
  837. +}
  838. +
  839. +static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
  840. +{
  841. + if (i != 0)
  842. + return -EINVAL;
  843. +
  844. + return 0;
  845. +}
  846. +
  847. +/* capture ioctls */
  848. +static int vidioc_querycap(struct file *file, void *priv,
  849. + struct v4l2_capability *cap)
  850. +{
  851. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  852. + u32 major;
  853. + u32 minor;
  854. +
  855. + vchiq_mmal_version(dev->instance, &major, &minor);
  856. +
  857. + strcpy(cap->driver, "bm2835 mmal");
  858. + snprintf(cap->card, sizeof(cap->card), "mmal service %d.%d",
  859. + major, minor);
  860. +
  861. + snprintf(cap->bus_info, sizeof(cap->bus_info),
  862. + "platform:%s", dev->v4l2_dev.name);
  863. + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
  864. + V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
  865. + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
  866. +
  867. + return 0;
  868. +}
  869. +
  870. +static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
  871. + struct v4l2_fmtdesc *f)
  872. +{
  873. + struct mmal_fmt *fmt;
  874. +
  875. + if (f->index >= ARRAY_SIZE(formats))
  876. + return -EINVAL;
  877. +
  878. + fmt = &formats[f->index];
  879. +
  880. + strlcpy(f->description, fmt->name, sizeof(f->description));
  881. + f->pixelformat = fmt->fourcc;
  882. + return 0;
  883. +}
  884. +
  885. +static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
  886. + struct v4l2_format *f)
  887. +{
  888. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  889. +
  890. + f->fmt.pix.width = dev->capture.width;
  891. + f->fmt.pix.height = dev->capture.height;
  892. + f->fmt.pix.field = V4L2_FIELD_NONE;
  893. + f->fmt.pix.pixelformat = dev->capture.fmt->fourcc;
  894. + f->fmt.pix.bytesperline =
  895. + (f->fmt.pix.width * dev->capture.fmt->depth) >> 3;
  896. + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
  897. + if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG
  898. + && f->fmt.pix.sizeimage < (100 << 10)) {
  899. + /* Need a minimum size for JPEG to account for EXIF. */
  900. + f->fmt.pix.sizeimage = (100 << 10);
  901. + }
  902. +
  903. + if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_YUYV ||
  904. + dev->capture.fmt->fourcc == V4L2_PIX_FMT_UYVY)
  905. + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
  906. + else
  907. + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
  908. + f->fmt.pix.priv = 0;
  909. +
  910. + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
  911. + __func__);
  912. + return 0;
  913. +}
  914. +
  915. +static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
  916. + struct v4l2_format *f)
  917. +{
  918. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  919. + struct mmal_fmt *mfmt;
  920. +
  921. + mfmt = get_format(f);
  922. + if (!mfmt) {
  923. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  924. + "Fourcc format (0x%08x) unknown.\n",
  925. + f->fmt.pix.pixelformat);
  926. + f->fmt.pix.pixelformat = formats[0].fourcc;
  927. + mfmt = get_format(f);
  928. + }
  929. +
  930. + f->fmt.pix.field = V4L2_FIELD_NONE;
  931. + /* image must be a multiple of 32 pixels wide and 16 lines high */
  932. + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 5,
  933. + &f->fmt.pix.height, 32, MAX_HEIGHT, 4, 0);
  934. + f->fmt.pix.bytesperline = (f->fmt.pix.width * mfmt->depth) >> 3;
  935. + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
  936. + if (f->fmt.pix.sizeimage < MIN_BUFFER_SIZE)
  937. + f->fmt.pix.sizeimage = MIN_BUFFER_SIZE;
  938. +
  939. + if (mfmt->fourcc == V4L2_PIX_FMT_YUYV ||
  940. + mfmt->fourcc == V4L2_PIX_FMT_UYVY)
  941. + f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
  942. + else
  943. + f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
  944. + f->fmt.pix.priv = 0;
  945. +
  946. + v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix,
  947. + __func__);
  948. + return 0;
  949. +}
  950. +
  951. +static int mmal_setup_components(struct bm2835_mmal_dev *dev,
  952. + struct v4l2_format *f)
  953. +{
  954. + int ret;
  955. + struct vchiq_mmal_port *port = NULL, *camera_port = NULL;
  956. + struct vchiq_mmal_component *encode_component = NULL;
  957. + struct mmal_fmt *mfmt = get_format(f);
  958. +
  959. + BUG_ON(!mfmt);
  960. +
  961. + if (dev->capture.encode_component) {
  962. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  963. + "vid_cap - disconnect previous tunnel\n");
  964. +
  965. + /* Disconnect any previous connection */
  966. + vchiq_mmal_port_connect_tunnel(dev->instance,
  967. + dev->capture.camera_port, NULL);
  968. + dev->capture.camera_port = NULL;
  969. + ret = vchiq_mmal_component_disable(dev->instance,
  970. + dev->capture.
  971. + encode_component);
  972. + if (ret)
  973. + v4l2_err(&dev->v4l2_dev,
  974. + "Failed to disable encode component %d\n",
  975. + ret);
  976. +
  977. + dev->capture.encode_component = NULL;
  978. + }
  979. + /* format dependant port setup */
  980. + switch (mfmt->mmal_component) {
  981. + case MMAL_COMPONENT_CAMERA:
  982. + /* Make a further decision on port based on resolution */
  983. + if (f->fmt.pix.width <= MAX_VIDEO_MODE_WIDTH
  984. + && f->fmt.pix.height <= MAX_VIDEO_MODE_HEIGHT)
  985. + camera_port = port =
  986. + &dev->component[MMAL_COMPONENT_CAMERA]->
  987. + output[MMAL_CAMERA_PORT_VIDEO];
  988. + else
  989. + camera_port = port =
  990. + &dev->component[MMAL_COMPONENT_CAMERA]->
  991. + output[MMAL_CAMERA_PORT_CAPTURE];
  992. + break;
  993. + case MMAL_COMPONENT_IMAGE_ENCODE:
  994. + encode_component = dev->component[MMAL_COMPONENT_IMAGE_ENCODE];
  995. + port = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
  996. + camera_port =
  997. + &dev->component[MMAL_COMPONENT_CAMERA]->
  998. + output[MMAL_CAMERA_PORT_CAPTURE];
  999. + break;
  1000. + case MMAL_COMPONENT_VIDEO_ENCODE:
  1001. + encode_component = dev->component[MMAL_COMPONENT_VIDEO_ENCODE];
  1002. + port = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
  1003. + camera_port =
  1004. + &dev->component[MMAL_COMPONENT_CAMERA]->
  1005. + output[MMAL_CAMERA_PORT_VIDEO];
  1006. + break;
  1007. + default:
  1008. + break;
  1009. + }
  1010. +
  1011. + if (!port)
  1012. + return -EINVAL;
  1013. +
  1014. + if (encode_component)
  1015. + camera_port->format.encoding = MMAL_ENCODING_OPAQUE;
  1016. + else
  1017. + camera_port->format.encoding = mfmt->mmal;
  1018. +
  1019. + camera_port->format.encoding_variant = 0;
  1020. + camera_port->es.video.width = f->fmt.pix.width;
  1021. + camera_port->es.video.height = f->fmt.pix.height;
  1022. + camera_port->es.video.crop.x = 0;
  1023. + camera_port->es.video.crop.y = 0;
  1024. + camera_port->es.video.crop.width = f->fmt.pix.width;
  1025. + camera_port->es.video.crop.height = f->fmt.pix.height;
  1026. + camera_port->es.video.frame_rate.num = 30;
  1027. + camera_port->es.video.frame_rate.den = 1;
  1028. +
  1029. + ret = vchiq_mmal_port_set_format(dev->instance, camera_port);
  1030. +
  1031. + if (!ret
  1032. + && camera_port ==
  1033. + &dev->component[MMAL_COMPONENT_CAMERA]->
  1034. + output[MMAL_CAMERA_PORT_VIDEO]) {
  1035. + bool overlay_enabled =
  1036. + !!dev->component[MMAL_COMPONENT_PREVIEW]->enabled;
  1037. + struct vchiq_mmal_port *preview_port =
  1038. + &dev->component[MMAL_COMPONENT_CAMERA]->
  1039. + output[MMAL_CAMERA_PORT_PREVIEW];
  1040. + /* Preview and encode ports need to match on resolution */
  1041. + if (overlay_enabled) {
  1042. + /* Need to disable the overlay before we can update
  1043. + * the resolution
  1044. + */
  1045. + ret =
  1046. + vchiq_mmal_port_disable(dev->instance,
  1047. + preview_port);
  1048. + if (!ret)
  1049. + ret =
  1050. + vchiq_mmal_port_connect_tunnel(
  1051. + dev->instance,
  1052. + preview_port,
  1053. + NULL);
  1054. + }
  1055. + preview_port->es.video.width = f->fmt.pix.width;
  1056. + preview_port->es.video.height = f->fmt.pix.height;
  1057. + preview_port->es.video.crop.x = 0;
  1058. + preview_port->es.video.crop.y = 0;
  1059. + preview_port->es.video.crop.width = f->fmt.pix.width;
  1060. + preview_port->es.video.crop.height = f->fmt.pix.height;
  1061. + preview_port->es.video.frame_rate.num = 30;
  1062. + preview_port->es.video.frame_rate.den = 1;
  1063. + ret = vchiq_mmal_port_set_format(dev->instance, preview_port);
  1064. + if (overlay_enabled) {
  1065. + ret = vchiq_mmal_port_connect_tunnel(
  1066. + dev->instance,
  1067. + preview_port,
  1068. + &dev->component[MMAL_COMPONENT_PREVIEW]->input[0]);
  1069. + if (!ret)
  1070. + ret = vchiq_mmal_port_enable(dev->instance,
  1071. + preview_port,
  1072. + NULL);
  1073. + }
  1074. + }
  1075. +
  1076. + if (ret) {
  1077. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  1078. + "%s failed to set format\n", __func__);
  1079. + /* ensure capture is not going to be tried */
  1080. + dev->capture.port = NULL;
  1081. + } else {
  1082. + if (encode_component) {
  1083. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  1084. + "vid_cap - set up encode comp\n");
  1085. +
  1086. + /* configure buffering */
  1087. + camera_port->current_buffer.size =
  1088. + camera_port->recommended_buffer.size;
  1089. + camera_port->current_buffer.num =
  1090. + camera_port->recommended_buffer.num;
  1091. +
  1092. + port->format.encoding = mfmt->mmal;
  1093. + port->format.encoding_variant = 0;
  1094. + /* Set any encoding specific parameters */
  1095. + switch (mfmt->mmal_component) {
  1096. + case MMAL_COMPONENT_VIDEO_ENCODE:
  1097. + port->format.bitrate =
  1098. + dev->capture.encode_bitrate;
  1099. + break;
  1100. + case MMAL_COMPONENT_IMAGE_ENCODE:
  1101. + /* Could set EXIF parameters here */
  1102. + break;
  1103. + default:
  1104. + break;
  1105. + }
  1106. + ret = vchiq_mmal_port_set_format(dev->instance, port);
  1107. +
  1108. + if (ret) {
  1109. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  1110. + "%s failed to set format\n", __func__);
  1111. + } else {
  1112. + ret = vchiq_mmal_component_enable(
  1113. + dev->instance,
  1114. + encode_component);
  1115. + if (ret) {
  1116. + v4l2_dbg(1, bcm2835_v4l2_debug,
  1117. + &dev->v4l2_dev,
  1118. + "%s Failed to enable encode components\n",
  1119. + __func__);
  1120. + } else {
  1121. + /* configure buffering */
  1122. + port->current_buffer.num = 1;
  1123. + port->current_buffer.size =
  1124. + f->fmt.pix.sizeimage;
  1125. + if (port->format.encoding ==
  1126. + MMAL_ENCODING_JPEG) {
  1127. + v4l2_dbg(1, bcm2835_v4l2_debug,
  1128. + &dev->v4l2_dev,
  1129. + "JPEG - fiddle buffer size\n");
  1130. + port->current_buffer.size =
  1131. + (f->fmt.pix.sizeimage <
  1132. + (100 << 10))
  1133. + ? (100 << 10) : f->fmt.pix.
  1134. + sizeimage;
  1135. + }
  1136. + v4l2_dbg(1, bcm2835_v4l2_debug,
  1137. + &dev->v4l2_dev,
  1138. + "vid_cap - current_buffer.size being set to %d\n",
  1139. + f->fmt.pix.sizeimage);
  1140. + port->current_buffer.alignment = 0;
  1141. + ret =
  1142. + vchiq_mmal_port_connect_tunnel(
  1143. + dev->instance,
  1144. + camera_port,
  1145. + &encode_component->input[0]);
  1146. + if (ret) {
  1147. + v4l2_dbg(1, bcm2835_v4l2_debug,
  1148. + &dev->v4l2_dev,
  1149. + "%s failed to create connection\n",
  1150. + __func__);
  1151. + /* ensure capture is not going to be tried */
  1152. + dev->capture.port = NULL;
  1153. + }
  1154. + }
  1155. + }
  1156. + } else {
  1157. + /* configure buffering */
  1158. + camera_port->current_buffer.num = 1;
  1159. + camera_port->current_buffer.size = f->fmt.pix.sizeimage;
  1160. + camera_port->current_buffer.alignment = 0;
  1161. + }
  1162. +
  1163. + if (!ret) {
  1164. + dev->capture.fmt = mfmt;
  1165. + dev->capture.stride = f->fmt.pix.bytesperline;
  1166. + dev->capture.width = port->es.video.crop.width;
  1167. + dev->capture.height = port->es.video.crop.height;
  1168. +
  1169. + /* select port for capture */
  1170. + dev->capture.port = port;
  1171. + dev->capture.camera_port = camera_port;
  1172. + dev->capture.encode_component = encode_component;
  1173. + }
  1174. + }
  1175. +
  1176. + /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */
  1177. + return ret;
  1178. +}
  1179. +
  1180. +static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
  1181. + struct v4l2_format *f)
  1182. +{
  1183. + int ret;
  1184. + struct bm2835_mmal_dev *dev = video_drvdata(file);
  1185. + struct mmal_fmt *mfmt;
  1186. +
  1187. + /* try the format to set valid parameters */
  1188. + ret = vidioc_try_fmt_vid_cap(file, priv, f);
  1189. + if (ret) {
  1190. + v4l2_err(&dev->v4l2_dev,
  1191. + "vid_cap - vidioc_try_fmt_vid_cap failed\n");
  1192. + return ret;
  1193. + }
  1194. +
  1195. + /* if a capture is running refuse to set format */
  1196. + if (vb2_is_busy(&dev->capture.vb_vidq)) {
  1197. + v4l2_info(&dev->v4l2_dev, "%s device busy\n", __func__);
  1198. + return -EBUSY;
  1199. + }
  1200. +
  1201. + /* If the format is unsupported v4l2 says we should switch to
  1202. + * a supported one and not return an error. */
  1203. + mfmt = get_format(f);
  1204. + if (!mfmt) {
  1205. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  1206. + "Fourcc format (0x%08x) unknown.\n",
  1207. + f->fmt.pix.pixelformat);
  1208. + f->fmt.pix.pixelformat = formats[0].fourcc;
  1209. + mfmt = get_format(f);
  1210. + }
  1211. +
  1212. + ret = mmal_setup_components(dev, f);
  1213. + if (ret != 0)
  1214. + v4l2_err(&dev->v4l2_dev,
  1215. + "%s: failed to setup mmal components: %d\n",
  1216. + __func__, ret);
  1217. +
  1218. + return ret;
  1219. +}
  1220. +
  1221. +static const struct v4l2_ioctl_ops camera0_ioctl_ops = {
  1222. + /* overlay */
  1223. + .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay,
  1224. + .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay,
  1225. + .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay,
  1226. + .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay,
  1227. + .vidioc_overlay = vidioc_overlay,
  1228. + .vidioc_g_fbuf = vidioc_g_fbuf,
  1229. +
  1230. + /* inputs */
  1231. + .vidioc_enum_input = vidioc_enum_input,
  1232. + .vidioc_g_input = vidioc_g_input,
  1233. + .vidioc_s_input = vidioc_s_input,
  1234. +
  1235. + /* capture */
  1236. + .vidioc_querycap = vidioc_querycap,
  1237. + .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
  1238. + .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
  1239. + .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
  1240. + .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
  1241. +
  1242. + /* buffer management */
  1243. + .vidioc_reqbufs = vb2_ioctl_reqbufs,
  1244. + .vidioc_create_bufs = vb2_ioctl_create_bufs,
  1245. + .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
  1246. + .vidioc_querybuf = vb2_ioctl_querybuf,
  1247. + .vidioc_qbuf = vb2_ioctl_qbuf,
  1248. + .vidioc_dqbuf = vb2_ioctl_dqbuf,
  1249. + .vidioc_streamon = vb2_ioctl_streamon,
  1250. + .vidioc_streamoff = vb2_ioctl_streamoff,
  1251. +
  1252. + .vidioc_log_status = v4l2_ctrl_log_status,
  1253. + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
  1254. + .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
  1255. +};
  1256. +
  1257. +/* ------------------------------------------------------------------
  1258. + Driver init/finalise
  1259. + ------------------------------------------------------------------*/
  1260. +
  1261. +static const struct v4l2_file_operations camera0_fops = {
  1262. + .owner = THIS_MODULE,
  1263. + .open = v4l2_fh_open,
  1264. + .release = vb2_fop_release,
  1265. + .read = vb2_fop_read,
  1266. + .poll = vb2_fop_poll,
  1267. + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
  1268. + .mmap = vb2_fop_mmap,
  1269. +};
  1270. +
  1271. +static struct video_device vdev_template = {
  1272. + .name = "camera0",
  1273. + .fops = &camera0_fops,
  1274. + .ioctl_ops = &camera0_ioctl_ops,
  1275. + .release = video_device_release_empty,
  1276. +};
  1277. +
  1278. +static int set_camera_parameters(struct vchiq_mmal_instance *instance,
  1279. + struct vchiq_mmal_component *camera)
  1280. +{
  1281. + int ret;
  1282. + struct mmal_parameter_camera_config cam_config = {
  1283. + .max_stills_w = MAX_WIDTH,
  1284. + .max_stills_h = MAX_HEIGHT,
  1285. + .stills_yuv422 = 1,
  1286. + .one_shot_stills = 1,
  1287. + .max_preview_video_w = 1920,
  1288. + .max_preview_video_h = 1088,
  1289. + .num_preview_video_frames = 3,
  1290. + .stills_capture_circular_buffer_height = 0,
  1291. + .fast_preview_resume = 0,
  1292. + .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC
  1293. + };
  1294. +
  1295. + ret = vchiq_mmal_port_parameter_set(instance, &camera->control,
  1296. + MMAL_PARAMETER_CAMERA_CONFIG,
  1297. + &cam_config, sizeof(cam_config));
  1298. + return ret;
  1299. +}
  1300. +
  1301. +/* MMAL instance and component init */
  1302. +static int __init mmal_init(struct bm2835_mmal_dev *dev)
  1303. +{
  1304. + int ret;
  1305. + struct mmal_es_format *format;
  1306. +
  1307. + ret = vchiq_mmal_init(&dev->instance);
  1308. + if (ret < 0)
  1309. + return ret;
  1310. +
  1311. + /* get the camera component ready */
  1312. + ret = vchiq_mmal_component_init(dev->instance, "ril.camera",
  1313. + &dev->component[MMAL_COMPONENT_CAMERA]);
  1314. + if (ret < 0)
  1315. + goto unreg_mmal;
  1316. +
  1317. + if (dev->component[MMAL_COMPONENT_CAMERA]->outputs <
  1318. + MMAL_CAMERA_PORT_COUNT) {
  1319. + ret = -EINVAL;
  1320. + goto unreg_camera;
  1321. + }
  1322. +
  1323. + ret = set_camera_parameters(dev->instance,
  1324. + dev->component[MMAL_COMPONENT_CAMERA]);
  1325. + if (ret < 0)
  1326. + goto unreg_camera;
  1327. +
  1328. + format =
  1329. + &dev->component[MMAL_COMPONENT_CAMERA]->
  1330. + output[MMAL_CAMERA_PORT_PREVIEW].format;
  1331. +
  1332. + format->encoding = MMAL_ENCODING_OPAQUE;
  1333. + format->encoding_variant = MMAL_ENCODING_I420;
  1334. +
  1335. + format->es->video.width = 1024;
  1336. + format->es->video.height = 768;
  1337. + format->es->video.crop.x = 0;
  1338. + format->es->video.crop.y = 0;
  1339. + format->es->video.crop.width = 1024;
  1340. + format->es->video.crop.height = 768;
  1341. + format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
  1342. + format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
  1343. +
  1344. + format =
  1345. + &dev->component[MMAL_COMPONENT_CAMERA]->
  1346. + output[MMAL_CAMERA_PORT_VIDEO].format;
  1347. +
  1348. + format->encoding = MMAL_ENCODING_OPAQUE;
  1349. + format->encoding_variant = MMAL_ENCODING_I420;
  1350. +
  1351. + format->es->video.width = 1024;
  1352. + format->es->video.height = 768;
  1353. + format->es->video.crop.x = 0;
  1354. + format->es->video.crop.y = 0;
  1355. + format->es->video.crop.width = 1024;
  1356. + format->es->video.crop.height = 768;
  1357. + format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM;
  1358. + format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN;
  1359. +
  1360. + format =
  1361. + &dev->component[MMAL_COMPONENT_CAMERA]->
  1362. + output[MMAL_CAMERA_PORT_CAPTURE].format;
  1363. +
  1364. + format->encoding = MMAL_ENCODING_OPAQUE;
  1365. +
  1366. + format->es->video.width = 2592;
  1367. + format->es->video.height = 1944;
  1368. + format->es->video.crop.x = 0;
  1369. + format->es->video.crop.y = 0;
  1370. + format->es->video.crop.width = 2592;
  1371. + format->es->video.crop.height = 1944;
  1372. + format->es->video.frame_rate.num = 30;
  1373. + format->es->video.frame_rate.den = 1;
  1374. +
  1375. + dev->capture.width = format->es->video.width;
  1376. + dev->capture.height = format->es->video.height;
  1377. + dev->capture.fmt = &formats[0];
  1378. + dev->capture.encode_component = NULL;
  1379. +
  1380. + /* get the preview component ready */
  1381. + ret = vchiq_mmal_component_init(
  1382. + dev->instance, "ril.video_render",
  1383. + &dev->component[MMAL_COMPONENT_PREVIEW]);
  1384. + if (ret < 0)
  1385. + goto unreg_camera;
  1386. +
  1387. + if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) {
  1388. + ret = -EINVAL;
  1389. + pr_debug("too few input ports %d needed %d\n",
  1390. + dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1);
  1391. + goto unreg_preview;
  1392. + }
  1393. +
  1394. + /* get the image encoder component ready */
  1395. + ret = vchiq_mmal_component_init(
  1396. + dev->instance, "ril.image_encode",
  1397. + &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
  1398. + if (ret < 0)
  1399. + goto unreg_preview;
  1400. +
  1401. + if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) {
  1402. + ret = -EINVAL;
  1403. + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
  1404. + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs,
  1405. + 1);
  1406. + goto unreg_image_encoder;
  1407. + }
  1408. +
  1409. + /* get the video encoder component ready */
  1410. + ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode",
  1411. + &dev->
  1412. + component[MMAL_COMPONENT_VIDEO_ENCODE]);
  1413. + if (ret < 0)
  1414. + goto unreg_image_encoder;
  1415. +
  1416. + if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) {
  1417. + ret = -EINVAL;
  1418. + v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n",
  1419. + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs,
  1420. + 1);
  1421. + goto unreg_vid_encoder;
  1422. + }
  1423. +
  1424. + {
  1425. + unsigned int enable = 1;
  1426. + vchiq_mmal_port_parameter_set(
  1427. + dev->instance,
  1428. + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
  1429. + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
  1430. + &enable, sizeof(enable));
  1431. +
  1432. + vchiq_mmal_port_parameter_set(dev->instance,
  1433. + &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->control,
  1434. + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
  1435. + &enable,
  1436. + sizeof(enable));
  1437. + }
  1438. + ret = bm2835_mmal_set_all_camera_controls(dev);
  1439. + if (ret < 0)
  1440. + goto unreg_vid_encoder;
  1441. +
  1442. + return 0;
  1443. +
  1444. +unreg_vid_encoder:
  1445. + pr_err("Cleanup: Destroy video encoder\n");
  1446. + vchiq_mmal_component_finalise(
  1447. + dev->instance,
  1448. + dev->component[MMAL_COMPONENT_VIDEO_ENCODE]);
  1449. +
  1450. +unreg_image_encoder:
  1451. + pr_err("Cleanup: Destroy image encoder\n");
  1452. + vchiq_mmal_component_finalise(
  1453. + dev->instance,
  1454. + dev->component[MMAL_COMPONENT_IMAGE_ENCODE]);
  1455. +
  1456. +unreg_preview:
  1457. + pr_err("Cleanup: Destroy video render\n");
  1458. + vchiq_mmal_component_finalise(dev->instance,
  1459. + dev->component[MMAL_COMPONENT_PREVIEW]);
  1460. +
  1461. +unreg_camera:
  1462. + pr_err("Cleanup: Destroy camera\n");
  1463. + vchiq_mmal_component_finalise(dev->instance,
  1464. + dev->component[MMAL_COMPONENT_CAMERA]);
  1465. +
  1466. +unreg_mmal:
  1467. + vchiq_mmal_finalise(dev->instance);
  1468. + return ret;
  1469. +}
  1470. +
  1471. +static int __init bm2835_mmal_init_device(struct bm2835_mmal_dev *dev,
  1472. + struct video_device *vfd)
  1473. +{
  1474. + int ret;
  1475. +
  1476. + *vfd = vdev_template;
  1477. +
  1478. + vfd->v4l2_dev = &dev->v4l2_dev;
  1479. +
  1480. + vfd->lock = &dev->mutex;
  1481. +
  1482. + vfd->queue = &dev->capture.vb_vidq;
  1483. +
  1484. + /* video device needs to be able to access instance data */
  1485. + video_set_drvdata(vfd, dev);
  1486. +
  1487. + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
  1488. + if (ret < 0)
  1489. + return ret;
  1490. +
  1491. + v4l2_info(vfd->v4l2_dev, "V4L2 device registered as %s\n",
  1492. + video_device_node_name(vfd));
  1493. +
  1494. + return 0;
  1495. +}
  1496. +
  1497. +static struct v4l2_format default_v4l2_format = {
  1498. + .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG,
  1499. + .fmt.pix.width = 1024,
  1500. + .fmt.pix.bytesperline = 1024 * 3 / 2,
  1501. + .fmt.pix.height = 768,
  1502. + .fmt.pix.sizeimage = 1<<18,
  1503. +};
  1504. +
  1505. +static int __init bm2835_mmal_init(void)
  1506. +{
  1507. + int ret;
  1508. + struct bm2835_mmal_dev *dev;
  1509. + struct vb2_queue *q;
  1510. +
  1511. + dev = kzalloc(sizeof(*gdev), GFP_KERNEL);
  1512. + if (!dev)
  1513. + return -ENOMEM;
  1514. +
  1515. + /* setup device defaults */
  1516. + dev->overlay.w.left = 150;
  1517. + dev->overlay.w.top = 50;
  1518. + dev->overlay.w.width = 1024;
  1519. + dev->overlay.w.height = 768;
  1520. + dev->overlay.clipcount = 0;
  1521. + dev->overlay.field = V4L2_FIELD_NONE;
  1522. +
  1523. + dev->capture.fmt = &formats[3]; /* JPEG */
  1524. +
  1525. + /* v4l device registration */
  1526. + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
  1527. + "%s", BM2835_MMAL_MODULE_NAME);
  1528. + ret = v4l2_device_register(NULL, &dev->v4l2_dev);
  1529. + if (ret)
  1530. + goto free_dev;
  1531. +
  1532. + /* setup v4l controls */
  1533. + ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler);
  1534. + if (ret < 0)
  1535. + goto unreg_dev;
  1536. + dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
  1537. +
  1538. + /* mmal init */
  1539. + ret = mmal_init(dev);
  1540. + if (ret < 0)
  1541. + goto unreg_dev;
  1542. +
  1543. + /* initialize queue */
  1544. + q = &dev->capture.vb_vidq;
  1545. + memset(q, 0, sizeof(*q));
  1546. + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1547. + q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
  1548. + q->drv_priv = dev;
  1549. + q->buf_struct_size = sizeof(struct mmal_buffer);
  1550. + q->ops = &bm2835_mmal_video_qops;
  1551. + q->mem_ops = &vb2_vmalloc_memops;
  1552. + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
  1553. + ret = vb2_queue_init(q);
  1554. + if (ret < 0)
  1555. + goto unreg_dev;
  1556. +
  1557. + /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */
  1558. + mutex_init(&dev->mutex);
  1559. +
  1560. + /* initialise video devices */
  1561. + ret = bm2835_mmal_init_device(dev, &dev->vdev);
  1562. + if (ret < 0)
  1563. + goto unreg_dev;
  1564. +
  1565. + ret = mmal_setup_components(dev, &default_v4l2_format);
  1566. + if (ret < 0) {
  1567. + v4l2_err(&dev->v4l2_dev,
  1568. + "%s: could not setup components\n", __func__);
  1569. + goto unreg_dev;
  1570. + }
  1571. +
  1572. + v4l2_info(&dev->v4l2_dev,
  1573. + "Broadcom 2835 MMAL video capture ver %s loaded.\n",
  1574. + BM2835_MMAL_VERSION);
  1575. +
  1576. + gdev = dev;
  1577. + return 0;
  1578. +
  1579. +unreg_dev:
  1580. + v4l2_ctrl_handler_free(&dev->ctrl_handler);
  1581. + v4l2_device_unregister(&dev->v4l2_dev);
  1582. +
  1583. +free_dev:
  1584. + kfree(dev);
  1585. +
  1586. + v4l2_err(&dev->v4l2_dev,
  1587. + "%s: error %d while loading driver\n",
  1588. + BM2835_MMAL_MODULE_NAME, ret);
  1589. +
  1590. + return ret;
  1591. +}
  1592. +
  1593. +static void __exit bm2835_mmal_exit(void)
  1594. +{
  1595. + if (!gdev)
  1596. + return;
  1597. +
  1598. + v4l2_info(&gdev->v4l2_dev, "unregistering %s\n",
  1599. + video_device_node_name(&gdev->vdev));
  1600. +
  1601. + video_unregister_device(&gdev->vdev);
  1602. +
  1603. + if (gdev->capture.encode_component) {
  1604. + v4l2_dbg(1, bcm2835_v4l2_debug, &gdev->v4l2_dev,
  1605. + "mmal_exit - disconnect tunnel\n");
  1606. + vchiq_mmal_port_connect_tunnel(gdev->instance,
  1607. + gdev->capture.camera_port, NULL);
  1608. + vchiq_mmal_component_disable(gdev->instance,
  1609. + gdev->capture.encode_component);
  1610. + }
  1611. + vchiq_mmal_component_disable(gdev->instance,
  1612. + gdev->component[MMAL_COMPONENT_CAMERA]);
  1613. +
  1614. + vchiq_mmal_component_finalise(gdev->instance,
  1615. + gdev->
  1616. + component[MMAL_COMPONENT_VIDEO_ENCODE]);
  1617. +
  1618. + vchiq_mmal_component_finalise(gdev->instance,
  1619. + gdev->
  1620. + component[MMAL_COMPONENT_IMAGE_ENCODE]);
  1621. +
  1622. + vchiq_mmal_component_finalise(gdev->instance,
  1623. + gdev->component[MMAL_COMPONENT_PREVIEW]);
  1624. +
  1625. + vchiq_mmal_component_finalise(gdev->instance,
  1626. + gdev->component[MMAL_COMPONENT_CAMERA]);
  1627. +
  1628. + vchiq_mmal_finalise(gdev->instance);
  1629. +
  1630. + v4l2_ctrl_handler_free(&gdev->ctrl_handler);
  1631. +
  1632. + v4l2_device_unregister(&gdev->v4l2_dev);
  1633. +
  1634. + kfree(gdev);
  1635. +}
  1636. +
  1637. +module_init(bm2835_mmal_init);
  1638. +module_exit(bm2835_mmal_exit);
  1639. --- /dev/null
  1640. +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h
  1641. @@ -0,0 +1,113 @@
  1642. +/*
  1643. + * Broadcom BM2835 V4L2 driver
  1644. + *
  1645. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  1646. + *
  1647. + * This file is subject to the terms and conditions of the GNU General Public
  1648. + * License. See the file COPYING in the main directory of this archive
  1649. + * for more details.
  1650. + *
  1651. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  1652. + * Dave Stevenson <dsteve@broadcom.com>
  1653. + * Simon Mellor <simellor@broadcom.com>
  1654. + * Luke Diamand <luked@broadcom.com>
  1655. + *
  1656. + * core driver device
  1657. + */
  1658. +
  1659. +#define V4L2_CTRL_COUNT 18 /* number of v4l controls */
  1660. +
  1661. +enum {
  1662. + MMAL_COMPONENT_CAMERA = 0,
  1663. + MMAL_COMPONENT_PREVIEW,
  1664. + MMAL_COMPONENT_IMAGE_ENCODE,
  1665. + MMAL_COMPONENT_VIDEO_ENCODE,
  1666. + MMAL_COMPONENT_COUNT
  1667. +};
  1668. +
  1669. +enum {
  1670. + MMAL_CAMERA_PORT_PREVIEW = 0,
  1671. + MMAL_CAMERA_PORT_VIDEO,
  1672. + MMAL_CAMERA_PORT_CAPTURE,
  1673. + MMAL_CAMERA_PORT_COUNT
  1674. +};
  1675. +
  1676. +#define PREVIEW_FRAME_RATE_NUM 30
  1677. +#define PREVIEW_FRAME_RATE_DEN 1
  1678. +
  1679. +#define PREVIEW_LAYER 2
  1680. +
  1681. +extern int bcm2835_v4l2_debug;
  1682. +
  1683. +struct bm2835_mmal_dev {
  1684. + /* v4l2 devices */
  1685. + struct v4l2_device v4l2_dev;
  1686. + struct video_device vdev;
  1687. + struct mutex mutex;
  1688. +
  1689. + /* controls */
  1690. + struct v4l2_ctrl_handler ctrl_handler;
  1691. + struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT];
  1692. + struct mmal_colourfx colourfx;
  1693. + int hflip;
  1694. + int vflip;
  1695. +
  1696. + /* allocated mmal instance and components */
  1697. + struct vchiq_mmal_instance *instance;
  1698. + struct vchiq_mmal_component *component[MMAL_COMPONENT_COUNT];
  1699. + int camera_use_count;
  1700. +
  1701. + struct v4l2_window overlay;
  1702. +
  1703. + struct {
  1704. + unsigned int width; /* width */
  1705. + unsigned int height; /* height */
  1706. + unsigned int stride; /* stride */
  1707. + struct mmal_fmt *fmt;
  1708. +
  1709. + /* H264 encode bitrate */
  1710. + int encode_bitrate;
  1711. + /* H264 bitrate mode. CBR/VBR */
  1712. + int encode_bitrate_mode;
  1713. + /* JPEG Q-factor */
  1714. + int q_factor;
  1715. +
  1716. + struct vb2_queue vb_vidq;
  1717. +
  1718. + /* VC start timestamp for streaming */
  1719. + s64 vc_start_timestamp;
  1720. + /* Kernel start timestamp for streaming */
  1721. + struct timeval kernel_start_ts;
  1722. +
  1723. + struct vchiq_mmal_port *port; /* port being used for capture */
  1724. + /* camera port being used for capture */
  1725. + struct vchiq_mmal_port *camera_port;
  1726. + /* component being used for encode */
  1727. + struct vchiq_mmal_component *encode_component;
  1728. + /* number of frames remaining which driver should capture */
  1729. + unsigned int frame_count;
  1730. + /* last frame completion */
  1731. + struct completion frame_cmplt;
  1732. +
  1733. + } capture;
  1734. +
  1735. +};
  1736. +
  1737. +int bm2835_mmal_init_controls(
  1738. + struct bm2835_mmal_dev *dev,
  1739. + struct v4l2_ctrl_handler *hdl);
  1740. +
  1741. +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev);
  1742. +
  1743. +
  1744. +/* Debug helpers */
  1745. +
  1746. +#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \
  1747. +{ \
  1748. + v4l2_dbg(level, debug, dev, \
  1749. +"%s: w %u h %u field %u pfmt 0x%x bpl %u sz_img %u colorspace 0x%x priv %u\n", \
  1750. + desc == NULL ? "" : desc, \
  1751. + (pix_fmt)->width, (pix_fmt)->height, (pix_fmt)->field, \
  1752. + (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \
  1753. + (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \
  1754. +}
  1755. --- /dev/null
  1756. +++ b/drivers/media/platform/bcm2835/controls.c
  1757. @@ -0,0 +1,725 @@
  1758. +/*
  1759. + * Broadcom BM2835 V4L2 driver
  1760. + *
  1761. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  1762. + *
  1763. + * This file is subject to the terms and conditions of the GNU General Public
  1764. + * License. See the file COPYING in the main directory of this archive
  1765. + * for more details.
  1766. + *
  1767. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  1768. + * Dave Stevenson <dsteve@broadcom.com>
  1769. + * Simon Mellor <simellor@broadcom.com>
  1770. + * Luke Diamand <luked@broadcom.com>
  1771. + */
  1772. +
  1773. +#include <linux/errno.h>
  1774. +#include <linux/kernel.h>
  1775. +#include <linux/module.h>
  1776. +#include <linux/slab.h>
  1777. +#include <media/videobuf2-vmalloc.h>
  1778. +#include <media/v4l2-device.h>
  1779. +#include <media/v4l2-ioctl.h>
  1780. +#include <media/v4l2-ctrls.h>
  1781. +#include <media/v4l2-fh.h>
  1782. +#include <media/v4l2-event.h>
  1783. +#include <media/v4l2-common.h>
  1784. +
  1785. +#include "mmal-common.h"
  1786. +#include "mmal-vchiq.h"
  1787. +#include "mmal-parameters.h"
  1788. +#include "bcm2835-camera.h"
  1789. +
  1790. +/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -24 to +24.
  1791. + * These are in 1/6th increments so the effective range is -4.0EV to +4.0EV.
  1792. + */
  1793. +static const s64 ev_bias_qmenu[] = {
  1794. + -24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 21, 24
  1795. +};
  1796. +
  1797. +/* Supported ISO values
  1798. + * ISOO = auto ISO
  1799. + */
  1800. +static const s64 iso_qmenu[] = {
  1801. + 0, 100, 200, 400, 800,
  1802. +};
  1803. +
  1804. +/* Supported video encode modes */
  1805. +static const s64 bitrate_mode_qmenu[] = {
  1806. + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
  1807. + (s64)V4L2_MPEG_VIDEO_BITRATE_MODE_CBR,
  1808. +};
  1809. +
  1810. +
  1811. +enum bm2835_mmal_ctrl_type {
  1812. + MMAL_CONTROL_TYPE_STD,
  1813. + MMAL_CONTROL_TYPE_STD_MENU,
  1814. + MMAL_CONTROL_TYPE_INT_MENU,
  1815. + MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */
  1816. +};
  1817. +
  1818. +struct bm2835_mmal_v4l2_ctrl;
  1819. +
  1820. +typedef int(bm2835_mmal_v4l2_ctrl_cb)(
  1821. + struct bm2835_mmal_dev *dev,
  1822. + struct v4l2_ctrl *ctrl,
  1823. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl);
  1824. +
  1825. +struct bm2835_mmal_v4l2_ctrl {
  1826. + u32 id; /* v4l2 control identifier */
  1827. + enum bm2835_mmal_ctrl_type type;
  1828. + /* control minimum value or
  1829. + * mask for MMAL_CONTROL_TYPE_STD_MENU */
  1830. + s32 min;
  1831. + s32 max; /* maximum value of control */
  1832. + s32 def; /* default value of control */
  1833. + s32 step; /* step size of the control */
  1834. + const s64 *imenu; /* integer menu array */
  1835. + u32 mmal_id; /* mmal parameter id */
  1836. + bm2835_mmal_v4l2_ctrl_cb *setter;
  1837. +};
  1838. +
  1839. +struct v4l2_to_mmal_effects_setting {
  1840. + u32 v4l2_effect;
  1841. + u32 mmal_effect;
  1842. + s32 col_fx_enable;
  1843. + s32 col_fx_fixed_cbcr;
  1844. + u32 u;
  1845. + u32 v;
  1846. + u32 num_effect_params;
  1847. + u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS];
  1848. +};
  1849. +
  1850. +static const struct v4l2_to_mmal_effects_setting
  1851. + v4l2_to_mmal_effects_values[] = {
  1852. + { V4L2_COLORFX_NONE, MMAL_PARAM_IMAGEFX_NONE,
  1853. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1854. + { V4L2_COLORFX_BW, MMAL_PARAM_IMAGEFX_NONE,
  1855. + 1, 0, 128, 128, 0, {0, 0, 0, 0, 0} },
  1856. + { V4L2_COLORFX_SEPIA, MMAL_PARAM_IMAGEFX_NONE,
  1857. + 1, 0, 87, 151, 0, {0, 0, 0, 0, 0} },
  1858. + { V4L2_COLORFX_NEGATIVE, MMAL_PARAM_IMAGEFX_NEGATIVE,
  1859. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1860. + { V4L2_COLORFX_EMBOSS, MMAL_PARAM_IMAGEFX_EMBOSS,
  1861. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1862. + { V4L2_COLORFX_SKETCH, MMAL_PARAM_IMAGEFX_SKETCH,
  1863. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1864. + { V4L2_COLORFX_SKY_BLUE, MMAL_PARAM_IMAGEFX_PASTEL,
  1865. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1866. + { V4L2_COLORFX_GRASS_GREEN, MMAL_PARAM_IMAGEFX_WATERCOLOUR,
  1867. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1868. + { V4L2_COLORFX_SKIN_WHITEN, MMAL_PARAM_IMAGEFX_WASHEDOUT,
  1869. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1870. + { V4L2_COLORFX_VIVID, MMAL_PARAM_IMAGEFX_SATURATION,
  1871. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1872. + { V4L2_COLORFX_AQUA, MMAL_PARAM_IMAGEFX_NONE,
  1873. + 1, 0, 171, 121, 0, {0, 0, 0, 0, 0} },
  1874. + { V4L2_COLORFX_ART_FREEZE, MMAL_PARAM_IMAGEFX_HATCH,
  1875. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1876. + { V4L2_COLORFX_SILHOUETTE, MMAL_PARAM_IMAGEFX_FILM,
  1877. + 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} },
  1878. + { V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE,
  1879. + 0, 0, 0, 0, 5, {1, 128, 160, 160, 48} },
  1880. + { V4L2_COLORFX_ANTIQUE, MMAL_PARAM_IMAGEFX_COLOURBALANCE,
  1881. + 0, 0, 0, 0, 3, {108, 274, 238, 0, 0} },
  1882. + { V4L2_COLORFX_SET_CBCR, MMAL_PARAM_IMAGEFX_NONE,
  1883. + 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} }
  1884. +};
  1885. +
  1886. +
  1887. +/* control handlers*/
  1888. +
  1889. +static int ctrl_set_rational(struct bm2835_mmal_dev *dev,
  1890. + struct v4l2_ctrl *ctrl,
  1891. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  1892. +{
  1893. + struct {
  1894. + s32 num; /**< Numerator */
  1895. + s32 den; /**< Denominator */
  1896. + } rational_value;
  1897. + struct vchiq_mmal_port *control;
  1898. +
  1899. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  1900. +
  1901. + rational_value.num = ctrl->val;
  1902. + rational_value.den = 100;
  1903. +
  1904. + return vchiq_mmal_port_parameter_set(dev->instance, control,
  1905. + mmal_ctrl->mmal_id,
  1906. + &rational_value,
  1907. + sizeof(rational_value));
  1908. +}
  1909. +
  1910. +static int ctrl_set_value(struct bm2835_mmal_dev *dev,
  1911. + struct v4l2_ctrl *ctrl,
  1912. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  1913. +{
  1914. + u32 u32_value;
  1915. + struct vchiq_mmal_port *control;
  1916. +
  1917. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  1918. +
  1919. + u32_value = ctrl->val;
  1920. +
  1921. + return vchiq_mmal_port_parameter_set(dev->instance, control,
  1922. + mmal_ctrl->mmal_id,
  1923. + &u32_value, sizeof(u32_value));
  1924. +}
  1925. +
  1926. +static int ctrl_set_rotate(struct bm2835_mmal_dev *dev,
  1927. + struct v4l2_ctrl *ctrl,
  1928. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  1929. +{
  1930. + int ret;
  1931. + u32 u32_value;
  1932. + struct vchiq_mmal_component *camera;
  1933. +
  1934. + camera = dev->component[MMAL_COMPONENT_CAMERA];
  1935. +
  1936. + u32_value = ((ctrl->val % 360) / 90) * 90;
  1937. +
  1938. + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
  1939. + mmal_ctrl->mmal_id,
  1940. + &u32_value, sizeof(u32_value));
  1941. + if (ret < 0)
  1942. + return ret;
  1943. +
  1944. + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
  1945. + mmal_ctrl->mmal_id,
  1946. + &u32_value, sizeof(u32_value));
  1947. + if (ret < 0)
  1948. + return ret;
  1949. +
  1950. + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
  1951. + mmal_ctrl->mmal_id,
  1952. + &u32_value, sizeof(u32_value));
  1953. +
  1954. + return ret;
  1955. +}
  1956. +
  1957. +static int ctrl_set_flip(struct bm2835_mmal_dev *dev,
  1958. + struct v4l2_ctrl *ctrl,
  1959. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  1960. +{
  1961. + int ret;
  1962. + u32 u32_value;
  1963. + struct vchiq_mmal_component *camera;
  1964. +
  1965. + if (ctrl->id == V4L2_CID_HFLIP)
  1966. + dev->hflip = ctrl->val;
  1967. + else
  1968. + dev->vflip = ctrl->val;
  1969. +
  1970. + camera = dev->component[MMAL_COMPONENT_CAMERA];
  1971. +
  1972. + if (dev->hflip && dev->vflip)
  1973. + u32_value = MMAL_PARAM_MIRROR_BOTH;
  1974. + else if (dev->hflip)
  1975. + u32_value = MMAL_PARAM_MIRROR_HORIZONTAL;
  1976. + else if (dev->vflip)
  1977. + u32_value = MMAL_PARAM_MIRROR_VERTICAL;
  1978. + else
  1979. + u32_value = MMAL_PARAM_MIRROR_NONE;
  1980. +
  1981. + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0],
  1982. + mmal_ctrl->mmal_id,
  1983. + &u32_value, sizeof(u32_value));
  1984. + if (ret < 0)
  1985. + return ret;
  1986. +
  1987. + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1],
  1988. + mmal_ctrl->mmal_id,
  1989. + &u32_value, sizeof(u32_value));
  1990. + if (ret < 0)
  1991. + return ret;
  1992. +
  1993. + ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2],
  1994. + mmal_ctrl->mmal_id,
  1995. + &u32_value, sizeof(u32_value));
  1996. +
  1997. + return ret;
  1998. +
  1999. +}
  2000. +
  2001. +static int ctrl_set_exposure(struct bm2835_mmal_dev *dev,
  2002. + struct v4l2_ctrl *ctrl,
  2003. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2004. +{
  2005. + u32 u32_value;
  2006. + struct vchiq_mmal_port *control;
  2007. +
  2008. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  2009. +
  2010. + switch (ctrl->val) {
  2011. + case V4L2_EXPOSURE_AUTO:
  2012. + u32_value = MMAL_PARAM_EXPOSUREMODE_AUTO;
  2013. + break;
  2014. +
  2015. + case V4L2_EXPOSURE_MANUAL:
  2016. + u32_value = MMAL_PARAM_EXPOSUREMODE_OFF;
  2017. + break;
  2018. +
  2019. + case V4L2_EXPOSURE_SHUTTER_PRIORITY:
  2020. + u32_value = MMAL_PARAM_EXPOSUREMODE_SPORTS;
  2021. + break;
  2022. +
  2023. + case V4L2_EXPOSURE_APERTURE_PRIORITY:
  2024. + u32_value = MMAL_PARAM_EXPOSUREMODE_NIGHT;
  2025. + break;
  2026. +
  2027. + }
  2028. +
  2029. + /* todo: what about the other ten modes there are MMAL parameters for */
  2030. + return vchiq_mmal_port_parameter_set(dev->instance, control,
  2031. + mmal_ctrl->mmal_id,
  2032. + &u32_value, sizeof(u32_value));
  2033. +}
  2034. +
  2035. +static int ctrl_set_metering_mode(struct bm2835_mmal_dev *dev,
  2036. + struct v4l2_ctrl *ctrl,
  2037. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2038. +{
  2039. + u32 u32_value;
  2040. + struct vchiq_mmal_port *control;
  2041. +
  2042. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  2043. +
  2044. + switch (ctrl->val) {
  2045. + case V4L2_EXPOSURE_METERING_AVERAGE:
  2046. + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
  2047. + break;
  2048. +
  2049. + case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
  2050. + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
  2051. + break;
  2052. +
  2053. + case V4L2_EXPOSURE_METERING_SPOT:
  2054. + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
  2055. + break;
  2056. +
  2057. + /* todo matrix weighting not added to Linux API till 3.9
  2058. + case V4L2_EXPOSURE_METERING_MATRIX:
  2059. + u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
  2060. + break;
  2061. + */
  2062. +
  2063. + }
  2064. +
  2065. + return vchiq_mmal_port_parameter_set(dev->instance, control,
  2066. + mmal_ctrl->mmal_id,
  2067. + &u32_value, sizeof(u32_value));
  2068. +}
  2069. +
  2070. +static int ctrl_set_awb_mode(struct bm2835_mmal_dev *dev,
  2071. + struct v4l2_ctrl *ctrl,
  2072. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2073. +{
  2074. + u32 u32_value;
  2075. + struct vchiq_mmal_port *control;
  2076. +
  2077. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  2078. +
  2079. + switch (ctrl->val) {
  2080. + case V4L2_WHITE_BALANCE_MANUAL:
  2081. + u32_value = MMAL_PARAM_AWBMODE_OFF;
  2082. + break;
  2083. +
  2084. + case V4L2_WHITE_BALANCE_AUTO:
  2085. + u32_value = MMAL_PARAM_AWBMODE_AUTO;
  2086. + break;
  2087. +
  2088. + case V4L2_WHITE_BALANCE_INCANDESCENT:
  2089. + u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT;
  2090. + break;
  2091. +
  2092. + case V4L2_WHITE_BALANCE_FLUORESCENT:
  2093. + u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT;
  2094. + break;
  2095. +
  2096. + case V4L2_WHITE_BALANCE_FLUORESCENT_H:
  2097. + u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN;
  2098. + break;
  2099. +
  2100. + case V4L2_WHITE_BALANCE_HORIZON:
  2101. + u32_value = MMAL_PARAM_AWBMODE_HORIZON;
  2102. + break;
  2103. +
  2104. + case V4L2_WHITE_BALANCE_DAYLIGHT:
  2105. + u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT;
  2106. + break;
  2107. +
  2108. + case V4L2_WHITE_BALANCE_FLASH:
  2109. + u32_value = MMAL_PARAM_AWBMODE_FLASH;
  2110. + break;
  2111. +
  2112. + case V4L2_WHITE_BALANCE_CLOUDY:
  2113. + u32_value = MMAL_PARAM_AWBMODE_CLOUDY;
  2114. + break;
  2115. +
  2116. + case V4L2_WHITE_BALANCE_SHADE:
  2117. + u32_value = MMAL_PARAM_AWBMODE_SHADE;
  2118. + break;
  2119. +
  2120. + }
  2121. +
  2122. + return vchiq_mmal_port_parameter_set(dev->instance, control,
  2123. + mmal_ctrl->mmal_id,
  2124. + &u32_value, sizeof(u32_value));
  2125. +}
  2126. +
  2127. +static int ctrl_set_image_effect(struct bm2835_mmal_dev *dev,
  2128. + struct v4l2_ctrl *ctrl,
  2129. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2130. +{
  2131. + int ret = -EINVAL;
  2132. + int i, j;
  2133. + struct vchiq_mmal_port *control;
  2134. + struct mmal_parameter_imagefx_parameters imagefx;
  2135. +
  2136. + for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) {
  2137. + if (ctrl->val == v4l2_to_mmal_effects_values[i].v4l2_effect) {
  2138. +
  2139. + imagefx.effect =
  2140. + v4l2_to_mmal_effects_values[i].mmal_effect;
  2141. + imagefx.num_effect_params =
  2142. + v4l2_to_mmal_effects_values[i].num_effect_params;
  2143. +
  2144. + if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS)
  2145. + imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS;
  2146. +
  2147. + for (j = 0; j < imagefx.num_effect_params; j++)
  2148. + imagefx.effect_parameter[j] =
  2149. + v4l2_to_mmal_effects_values[i].effect_params[j];
  2150. +
  2151. + dev->colourfx.enable =
  2152. + v4l2_to_mmal_effects_values[i].col_fx_enable;
  2153. + if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) {
  2154. + dev->colourfx.u =
  2155. + v4l2_to_mmal_effects_values[i].u;
  2156. + dev->colourfx.v =
  2157. + v4l2_to_mmal_effects_values[i].v;
  2158. + }
  2159. +
  2160. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  2161. +
  2162. + ret = vchiq_mmal_port_parameter_set(
  2163. + dev->instance, control,
  2164. + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
  2165. + &imagefx, sizeof(imagefx));
  2166. + if (ret)
  2167. + goto exit;
  2168. +
  2169. + ret = vchiq_mmal_port_parameter_set(
  2170. + dev->instance, control,
  2171. + MMAL_PARAMETER_COLOUR_EFFECT,
  2172. + &dev->colourfx, sizeof(dev->colourfx));
  2173. + }
  2174. + }
  2175. +
  2176. +exit:
  2177. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  2178. + "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n",
  2179. + mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect,
  2180. + dev->colourfx.enable ? "true" : "false",
  2181. + dev->colourfx.u, dev->colourfx.v,
  2182. + ret, (ret == 0 ? 0 : -EINVAL));
  2183. + return (ret == 0 ? 0 : EINVAL);
  2184. +}
  2185. +
  2186. +static int ctrl_set_colfx(struct bm2835_mmal_dev *dev,
  2187. + struct v4l2_ctrl *ctrl,
  2188. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2189. +{
  2190. + int ret = -EINVAL;
  2191. + struct vchiq_mmal_port *control;
  2192. +
  2193. + control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
  2194. +
  2195. + dev->colourfx.enable = (ctrl->val & 0xff00) >> 8;
  2196. + dev->colourfx.enable = ctrl->val & 0xff;
  2197. +
  2198. + ret = vchiq_mmal_port_parameter_set(dev->instance, control,
  2199. + MMAL_PARAMETER_COLOUR_EFFECT,
  2200. + &dev->colourfx, sizeof(dev->colourfx));
  2201. +
  2202. + v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
  2203. + "After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n",
  2204. + mmal_ctrl, ctrl->id, ctrl->val, ret,
  2205. + (ret == 0 ? 0 : -EINVAL));
  2206. + return (ret == 0 ? 0 : EINVAL);
  2207. +}
  2208. +
  2209. +static int ctrl_set_bitrate(struct bm2835_mmal_dev *dev,
  2210. + struct v4l2_ctrl *ctrl,
  2211. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2212. +{
  2213. + int ret;
  2214. + struct vchiq_mmal_port *encoder_out;
  2215. +
  2216. + dev->capture.encode_bitrate = ctrl->val;
  2217. +
  2218. + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
  2219. +
  2220. + ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
  2221. + mmal_ctrl->mmal_id,
  2222. + &ctrl->val, sizeof(ctrl->val));
  2223. + ret = 0;
  2224. + return ret;
  2225. +}
  2226. +
  2227. +static int ctrl_set_bitrate_mode(struct bm2835_mmal_dev *dev,
  2228. + struct v4l2_ctrl *ctrl,
  2229. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2230. +{
  2231. + u32 bitrate_mode;
  2232. + struct vchiq_mmal_port *encoder_out;
  2233. +
  2234. + encoder_out = &dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->output[0];
  2235. +
  2236. + dev->capture.encode_bitrate_mode = ctrl->val;
  2237. + switch (ctrl->val) {
  2238. + default:
  2239. + case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
  2240. + bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE;
  2241. + break;
  2242. + case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
  2243. + bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT;
  2244. + break;
  2245. + }
  2246. +
  2247. + vchiq_mmal_port_parameter_set(dev->instance, encoder_out,
  2248. + mmal_ctrl->mmal_id,
  2249. + &bitrate_mode,
  2250. + sizeof(bitrate_mode));
  2251. + return 0;
  2252. +}
  2253. +
  2254. +static int ctrl_set_q_factor(struct bm2835_mmal_dev *dev,
  2255. + struct v4l2_ctrl *ctrl,
  2256. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
  2257. +{
  2258. + u32 u32_value;
  2259. + struct vchiq_mmal_port *jpeg_out;
  2260. +
  2261. + jpeg_out = &dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->output[0];
  2262. +
  2263. + u32_value = ctrl->val;
  2264. +
  2265. + return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out,
  2266. + mmal_ctrl->mmal_id,
  2267. + &u32_value, sizeof(u32_value));
  2268. +}
  2269. +
  2270. +static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
  2271. +{
  2272. + struct bm2835_mmal_dev *dev =
  2273. + container_of(ctrl->handler, struct bm2835_mmal_dev,
  2274. + ctrl_handler);
  2275. + const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv;
  2276. +
  2277. + if ((mmal_ctrl == NULL) ||
  2278. + (mmal_ctrl->id != ctrl->id) ||
  2279. + (mmal_ctrl->setter == NULL)) {
  2280. + pr_warn("mmal_ctrl:%p ctrl id:%d\n", mmal_ctrl, ctrl->id);
  2281. + return -EINVAL;
  2282. + }
  2283. +
  2284. + return mmal_ctrl->setter(dev, ctrl, mmal_ctrl);
  2285. +}
  2286. +
  2287. +static const struct v4l2_ctrl_ops bm2835_mmal_ctrl_ops = {
  2288. + .s_ctrl = bm2835_mmal_s_ctrl,
  2289. +};
  2290. +
  2291. +
  2292. +
  2293. +static const struct bm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = {
  2294. + {
  2295. + V4L2_CID_SATURATION, MMAL_CONTROL_TYPE_STD,
  2296. + -100, 100, 0, 1, NULL,
  2297. + MMAL_PARAMETER_SATURATION, &ctrl_set_rational
  2298. + },
  2299. + {
  2300. + V4L2_CID_SHARPNESS, MMAL_CONTROL_TYPE_STD,
  2301. + -100, 100, 0, 1, NULL,
  2302. + MMAL_PARAMETER_SHARPNESS, &ctrl_set_rational
  2303. + },
  2304. + {
  2305. + V4L2_CID_CONTRAST, MMAL_CONTROL_TYPE_STD,
  2306. + -100, 100, 0, 1, NULL,
  2307. + MMAL_PARAMETER_CONTRAST, &ctrl_set_rational
  2308. + },
  2309. + {
  2310. + V4L2_CID_BRIGHTNESS, MMAL_CONTROL_TYPE_STD,
  2311. + 0, 100, 50, 1, NULL,
  2312. + MMAL_PARAMETER_BRIGHTNESS, &ctrl_set_rational
  2313. + },
  2314. + {
  2315. + V4L2_CID_ISO_SENSITIVITY, MMAL_CONTROL_TYPE_INT_MENU,
  2316. + 0, ARRAY_SIZE(iso_qmenu) - 1, 0, 1, iso_qmenu,
  2317. + MMAL_PARAMETER_ISO, &ctrl_set_value
  2318. + },
  2319. + {
  2320. + V4L2_CID_IMAGE_STABILIZATION, MMAL_CONTROL_TYPE_STD,
  2321. + 0, 1, 0, 1, NULL,
  2322. + MMAL_PARAMETER_VIDEO_STABILISATION, &ctrl_set_value
  2323. + },
  2324. +/* {
  2325. + 0, MMAL_CONTROL_TYPE_CLUSTER, 3, 1, 0, NULL, 0, NULL
  2326. + },
  2327. +*/ {
  2328. + V4L2_CID_EXPOSURE_AUTO, MMAL_CONTROL_TYPE_STD_MENU,
  2329. + ~0x03, 3, V4L2_EXPOSURE_AUTO, 0, NULL,
  2330. + MMAL_PARAMETER_EXPOSURE_MODE, &ctrl_set_exposure
  2331. + },
  2332. +/* todo this needs mixing in with set exposure
  2333. + {
  2334. + V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
  2335. + },
  2336. + */
  2337. + {
  2338. + V4L2_CID_AUTO_EXPOSURE_BIAS, MMAL_CONTROL_TYPE_INT_MENU,
  2339. + 0, ARRAY_SIZE(ev_bias_qmenu) - 1,
  2340. + (ARRAY_SIZE(ev_bias_qmenu)+1)/2 - 1, 0, ev_bias_qmenu,
  2341. + MMAL_PARAMETER_EXPOSURE_COMP, &ctrl_set_value
  2342. + },
  2343. + {
  2344. + V4L2_CID_EXPOSURE_METERING,
  2345. + MMAL_CONTROL_TYPE_STD_MENU,
  2346. + ~0x7, 2, V4L2_EXPOSURE_METERING_AVERAGE, 0, NULL,
  2347. + MMAL_PARAMETER_EXP_METERING_MODE, &ctrl_set_metering_mode
  2348. + },
  2349. + {
  2350. + V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
  2351. + MMAL_CONTROL_TYPE_STD_MENU,
  2352. + ~0x3fe, 9, V4L2_WHITE_BALANCE_AUTO, 0, NULL,
  2353. + MMAL_PARAMETER_AWB_MODE, &ctrl_set_awb_mode
  2354. + },
  2355. + {
  2356. + V4L2_CID_COLORFX, MMAL_CONTROL_TYPE_STD_MENU,
  2357. + 0, 15, V4L2_COLORFX_NONE, 0, NULL,
  2358. + MMAL_PARAMETER_IMAGE_EFFECT, &ctrl_set_image_effect
  2359. + },
  2360. + {
  2361. + V4L2_CID_COLORFX_CBCR, MMAL_CONTROL_TYPE_STD,
  2362. + 0, 0xffff, 0x8080, 1, NULL,
  2363. + MMAL_PARAMETER_COLOUR_EFFECT, &ctrl_set_colfx
  2364. + },
  2365. + {
  2366. + V4L2_CID_ROTATE, MMAL_CONTROL_TYPE_STD,
  2367. + 0, 360, 0, 90, NULL,
  2368. + MMAL_PARAMETER_ROTATION, &ctrl_set_rotate
  2369. + },
  2370. + {
  2371. + V4L2_CID_HFLIP, MMAL_CONTROL_TYPE_STD,
  2372. + 0, 1, 0, 1, NULL,
  2373. + MMAL_PARAMETER_MIRROR, &ctrl_set_flip
  2374. + },
  2375. + {
  2376. + V4L2_CID_VFLIP, MMAL_CONTROL_TYPE_STD,
  2377. + 0, 1, 0, 1, NULL,
  2378. + MMAL_PARAMETER_MIRROR, &ctrl_set_flip
  2379. + },
  2380. + {
  2381. + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
  2382. + 0, ARRAY_SIZE(bitrate_mode_qmenu) - 1,
  2383. + 0, 0, bitrate_mode_qmenu,
  2384. + MMAL_PARAMETER_RATECONTROL, &ctrl_set_bitrate_mode
  2385. + },
  2386. + {
  2387. + V4L2_CID_MPEG_VIDEO_BITRATE, MMAL_CONTROL_TYPE_STD,
  2388. + 25*1000, 25*1000*1000, 10*1000*1000, 25*1000, NULL,
  2389. + MMAL_PARAMETER_VIDEO_BIT_RATE, &ctrl_set_bitrate
  2390. + },
  2391. + {
  2392. + V4L2_CID_JPEG_COMPRESSION_QUALITY, MMAL_CONTROL_TYPE_STD,
  2393. + 0, 100,
  2394. + 30, 1, NULL,
  2395. + MMAL_PARAMETER_JPEG_Q_FACTOR, &ctrl_set_q_factor
  2396. + },
  2397. +};
  2398. +
  2399. +int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
  2400. +{
  2401. + int c;
  2402. + int ret;
  2403. +
  2404. + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
  2405. + if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) {
  2406. + ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c],
  2407. + &v4l2_ctrls[c]);
  2408. + if (ret)
  2409. + break;
  2410. + }
  2411. + }
  2412. + return ret;
  2413. +}
  2414. +
  2415. +int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
  2416. + struct v4l2_ctrl_handler *hdl)
  2417. +{
  2418. + int c;
  2419. + const struct bm2835_mmal_v4l2_ctrl *ctrl;
  2420. +
  2421. + v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT);
  2422. +
  2423. + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
  2424. + ctrl = &v4l2_ctrls[c];
  2425. +
  2426. + switch (ctrl->type) {
  2427. + case MMAL_CONTROL_TYPE_STD:
  2428. + dev->ctrls[c] = v4l2_ctrl_new_std(hdl,
  2429. + &bm2835_mmal_ctrl_ops, ctrl->id,
  2430. + ctrl->min, ctrl->max, ctrl->step, ctrl->def);
  2431. + break;
  2432. +
  2433. + case MMAL_CONTROL_TYPE_STD_MENU:
  2434. + dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
  2435. + &bm2835_mmal_ctrl_ops, ctrl->id,
  2436. + ctrl->max, ctrl->min, ctrl->def);
  2437. + break;
  2438. +
  2439. + case MMAL_CONTROL_TYPE_INT_MENU:
  2440. + dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,
  2441. + &bm2835_mmal_ctrl_ops, ctrl->id,
  2442. + ctrl->max, ctrl->def, ctrl->imenu);
  2443. + break;
  2444. +
  2445. + case MMAL_CONTROL_TYPE_CLUSTER:
  2446. + /* skip this entry when constructing controls */
  2447. + continue;
  2448. + }
  2449. +
  2450. + if (hdl->error)
  2451. + break;
  2452. +
  2453. + dev->ctrls[c]->priv = (void *)ctrl;
  2454. + }
  2455. +
  2456. + if (hdl->error) {
  2457. + pr_err("error adding control %d/%d id 0x%x\n", c,
  2458. + V4L2_CTRL_COUNT, ctrl->id);
  2459. + return hdl->error;
  2460. + }
  2461. +
  2462. + for (c = 0; c < V4L2_CTRL_COUNT; c++) {
  2463. + ctrl = &v4l2_ctrls[c];
  2464. +
  2465. + switch (ctrl->type) {
  2466. + case MMAL_CONTROL_TYPE_CLUSTER:
  2467. + v4l2_ctrl_auto_cluster(ctrl->min,
  2468. + &dev->ctrls[c+1],
  2469. + ctrl->max,
  2470. + ctrl->def);
  2471. + break;
  2472. +
  2473. + case MMAL_CONTROL_TYPE_STD:
  2474. + case MMAL_CONTROL_TYPE_STD_MENU:
  2475. + case MMAL_CONTROL_TYPE_INT_MENU:
  2476. + break;
  2477. + }
  2478. +
  2479. + }
  2480. +
  2481. + return 0;
  2482. +}
  2483. --- /dev/null
  2484. +++ b/drivers/media/platform/bcm2835/mmal-common.h
  2485. @@ -0,0 +1,51 @@
  2486. +/*
  2487. + * Broadcom BM2835 V4L2 driver
  2488. + *
  2489. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  2490. + *
  2491. + * This file is subject to the terms and conditions of the GNU General Public
  2492. + * License. See the file COPYING in the main directory of this archive
  2493. + * for more details.
  2494. + *
  2495. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  2496. + * Dave Stevenson <dsteve@broadcom.com>
  2497. + * Simon Mellor <simellor@broadcom.com>
  2498. + * Luke Diamand <luked@broadcom.com>
  2499. + *
  2500. + * MMAL structures
  2501. + *
  2502. + */
  2503. +
  2504. +#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24))
  2505. +#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l')
  2506. +
  2507. +/** Special value signalling that time is not known */
  2508. +#define MMAL_TIME_UNKNOWN (1LL<<63)
  2509. +
  2510. +/* mapping between v4l and mmal video modes */
  2511. +struct mmal_fmt {
  2512. + char *name;
  2513. + u32 fourcc; /* v4l2 format id */
  2514. + u32 mmal;
  2515. + int depth;
  2516. + u32 mmal_component; /* MMAL component index to be used to encode */
  2517. +};
  2518. +
  2519. +/* buffer for one video frame */
  2520. +struct mmal_buffer {
  2521. + /* v4l buffer data -- must be first */
  2522. + struct vb2_buffer vb;
  2523. +
  2524. + /* list of buffers available */
  2525. + struct list_head list;
  2526. +
  2527. + void *buffer; /* buffer pointer */
  2528. + unsigned long buffer_size; /* size of allocated buffer */
  2529. +};
  2530. +
  2531. +/* */
  2532. +struct mmal_colourfx {
  2533. + s32 enable;
  2534. + u32 u;
  2535. + u32 v;
  2536. +};
  2537. --- /dev/null
  2538. +++ b/drivers/media/platform/bcm2835/mmal-encodings.h
  2539. @@ -0,0 +1,93 @@
  2540. +/*
  2541. + * Broadcom BM2835 V4L2 driver
  2542. + *
  2543. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  2544. + *
  2545. + * This file is subject to the terms and conditions of the GNU General Public
  2546. + * License. See the file COPYING in the main directory of this archive
  2547. + * for more details.
  2548. + *
  2549. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  2550. + * Dave Stevenson <dsteve@broadcom.com>
  2551. + * Simon Mellor <simellor@broadcom.com>
  2552. + * Luke Diamand <luked@broadcom.com>
  2553. + */
  2554. +
  2555. +#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4')
  2556. +#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3')
  2557. +#define MMAL_ENCODING_MP4V MMAL_FOURCC('M', 'P', '4', 'V')
  2558. +#define MMAL_ENCODING_MP2V MMAL_FOURCC('M', 'P', '2', 'V')
  2559. +#define MMAL_ENCODING_MP1V MMAL_FOURCC('M', 'P', '1', 'V')
  2560. +#define MMAL_ENCODING_WMV3 MMAL_FOURCC('W', 'M', 'V', '3')
  2561. +#define MMAL_ENCODING_WMV2 MMAL_FOURCC('W', 'M', 'V', '2')
  2562. +#define MMAL_ENCODING_WMV1 MMAL_FOURCC('W', 'M', 'V', '1')
  2563. +#define MMAL_ENCODING_WVC1 MMAL_FOURCC('W', 'V', 'C', '1')
  2564. +#define MMAL_ENCODING_VP8 MMAL_FOURCC('V', 'P', '8', ' ')
  2565. +#define MMAL_ENCODING_VP7 MMAL_FOURCC('V', 'P', '7', ' ')
  2566. +#define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ')
  2567. +#define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O')
  2568. +#define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K')
  2569. +
  2570. +#define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G')
  2571. +#define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ')
  2572. +#define MMAL_ENCODING_PNG MMAL_FOURCC('P', 'N', 'G', ' ')
  2573. +#define MMAL_ENCODING_PPM MMAL_FOURCC('P', 'P', 'M', ' ')
  2574. +#define MMAL_ENCODING_TGA MMAL_FOURCC('T', 'G', 'A', ' ')
  2575. +#define MMAL_ENCODING_BMP MMAL_FOURCC('B', 'M', 'P', ' ')
  2576. +
  2577. +#define MMAL_ENCODING_I420 MMAL_FOURCC('I', '4', '2', '0')
  2578. +#define MMAL_ENCODING_I420_SLICE MMAL_FOURCC('S', '4', '2', '0')
  2579. +#define MMAL_ENCODING_YV12 MMAL_FOURCC('Y', 'V', '1', '2')
  2580. +#define MMAL_ENCODING_I422 MMAL_FOURCC('I', '4', '2', '2')
  2581. +#define MMAL_ENCODING_I422_SLICE MMAL_FOURCC('S', '4', '2', '2')
  2582. +#define MMAL_ENCODING_YUYV MMAL_FOURCC('Y', 'U', 'Y', 'V')
  2583. +#define MMAL_ENCODING_YVYU MMAL_FOURCC('Y', 'V', 'Y', 'U')
  2584. +#define MMAL_ENCODING_UYVY MMAL_FOURCC('U', 'Y', 'V', 'Y')
  2585. +#define MMAL_ENCODING_VYUY MMAL_FOURCC('V', 'Y', 'U', 'Y')
  2586. +#define MMAL_ENCODING_NV12 MMAL_FOURCC('N', 'V', '1', '2')
  2587. +#define MMAL_ENCODING_NV21 MMAL_FOURCC('N', 'V', '2', '1')
  2588. +#define MMAL_ENCODING_ARGB MMAL_FOURCC('A', 'R', 'G', 'B')
  2589. +#define MMAL_ENCODING_RGBA MMAL_FOURCC('R', 'G', 'B', 'A')
  2590. +#define MMAL_ENCODING_ABGR MMAL_FOURCC('A', 'B', 'G', 'R')
  2591. +#define MMAL_ENCODING_BGRA MMAL_FOURCC('B', 'G', 'R', 'A')
  2592. +#define MMAL_ENCODING_RGB16 MMAL_FOURCC('R', 'G', 'B', '2')
  2593. +#define MMAL_ENCODING_RGB24 MMAL_FOURCC('R', 'G', 'B', '3')
  2594. +#define MMAL_ENCODING_RGB32 MMAL_FOURCC('R', 'G', 'B', '4')
  2595. +#define MMAL_ENCODING_BGR16 MMAL_FOURCC('B', 'G', 'R', '2')
  2596. +#define MMAL_ENCODING_BGR24 MMAL_FOURCC('B', 'G', 'R', '3')
  2597. +#define MMAL_ENCODING_BGR32 MMAL_FOURCC('B', 'G', 'R', '4')
  2598. +
  2599. +/** SAND Video (YUVUV128) format, native format understood by VideoCore.
  2600. + * This format is *not* opaque - if requested you will receive full frames
  2601. + * of YUV_UV video.
  2602. + */
  2603. +#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S', 'A', 'N', 'D')
  2604. +
  2605. +/** VideoCore opaque image format, image handles are returned to
  2606. + * the host but not the actual image data.
  2607. + */
  2608. +#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V')
  2609. +
  2610. +/** An EGL image handle
  2611. + */
  2612. +#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I')
  2613. +
  2614. +/* }@ */
  2615. +
  2616. +/** \name Pre-defined audio encodings */
  2617. +/* @{ */
  2618. +#define MMAL_ENCODING_PCM_UNSIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'U')
  2619. +#define MMAL_ENCODING_PCM_UNSIGNED_LE MMAL_FOURCC('p', 'c', 'm', 'u')
  2620. +#define MMAL_ENCODING_PCM_SIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'S')
  2621. +#define MMAL_ENCODING_PCM_SIGNED_LE MMAL_FOURCC('p', 'c', 'm', 's')
  2622. +#define MMAL_ENCODING_PCM_FLOAT_BE MMAL_FOURCC('P', 'C', 'M', 'F')
  2623. +#define MMAL_ENCODING_PCM_FLOAT_LE MMAL_FOURCC('p', 'c', 'm', 'f')
  2624. +
  2625. +/* Pre-defined H264 encoding variants */
  2626. +
  2627. +/** ISO 14496-10 Annex B byte stream format */
  2628. +#define MMAL_ENCODING_VARIANT_H264_DEFAULT 0
  2629. +/** ISO 14496-15 AVC stream format */
  2630. +#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1')
  2631. +/** Implicitly delineated NAL units without emulation prevention */
  2632. +#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ')
  2633. --- /dev/null
  2634. +++ b/drivers/media/platform/bcm2835/mmal-msg-common.h
  2635. @@ -0,0 +1,50 @@
  2636. +/*
  2637. + * Broadcom BM2835 V4L2 driver
  2638. + *
  2639. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  2640. + *
  2641. + * This file is subject to the terms and conditions of the GNU General Public
  2642. + * License. See the file COPYING in the main directory of this archive
  2643. + * for more details.
  2644. + *
  2645. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  2646. + * Dave Stevenson <dsteve@broadcom.com>
  2647. + * Simon Mellor <simellor@broadcom.com>
  2648. + * Luke Diamand <luked@broadcom.com>
  2649. + */
  2650. +
  2651. +#ifndef MMAL_MSG_COMMON_H
  2652. +#define MMAL_MSG_COMMON_H
  2653. +
  2654. +enum mmal_msg_status {
  2655. + MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */
  2656. + MMAL_MSG_STATUS_ENOMEM, /**< Out of memory */
  2657. + MMAL_MSG_STATUS_ENOSPC, /**< Out of resources other than memory */
  2658. + MMAL_MSG_STATUS_EINVAL, /**< Argument is invalid */
  2659. + MMAL_MSG_STATUS_ENOSYS, /**< Function not implemented */
  2660. + MMAL_MSG_STATUS_ENOENT, /**< No such file or directory */
  2661. + MMAL_MSG_STATUS_ENXIO, /**< No such device or address */
  2662. + MMAL_MSG_STATUS_EIO, /**< I/O error */
  2663. + MMAL_MSG_STATUS_ESPIPE, /**< Illegal seek */
  2664. + MMAL_MSG_STATUS_ECORRUPT, /**< Data is corrupt \attention */
  2665. + MMAL_MSG_STATUS_ENOTREADY, /**< Component is not ready */
  2666. + MMAL_MSG_STATUS_ECONFIG, /**< Component is not configured */
  2667. + MMAL_MSG_STATUS_EISCONN, /**< Port is already connected */
  2668. + MMAL_MSG_STATUS_ENOTCONN, /**< Port is disconnected */
  2669. + MMAL_MSG_STATUS_EAGAIN, /**< Resource temporarily unavailable. */
  2670. + MMAL_MSG_STATUS_EFAULT, /**< Bad address */
  2671. +};
  2672. +
  2673. +struct mmal_rect {
  2674. + s32 x; /**< x coordinate (from left) */
  2675. + s32 y; /**< y coordinate (from top) */
  2676. + s32 width; /**< width */
  2677. + s32 height; /**< height */
  2678. +};
  2679. +
  2680. +struct mmal_rational {
  2681. + s32 num; /**< Numerator */
  2682. + s32 den; /**< Denominator */
  2683. +};
  2684. +
  2685. +#endif /* MMAL_MSG_COMMON_H */
  2686. --- /dev/null
  2687. +++ b/drivers/media/platform/bcm2835/mmal-msg-format.h
  2688. @@ -0,0 +1,81 @@
  2689. +/*
  2690. + * Broadcom BM2835 V4L2 driver
  2691. + *
  2692. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  2693. + *
  2694. + * This file is subject to the terms and conditions of the GNU General Public
  2695. + * License. See the file COPYING in the main directory of this archive
  2696. + * for more details.
  2697. + *
  2698. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  2699. + * Dave Stevenson <dsteve@broadcom.com>
  2700. + * Simon Mellor <simellor@broadcom.com>
  2701. + * Luke Diamand <luked@broadcom.com>
  2702. + */
  2703. +
  2704. +#ifndef MMAL_MSG_FORMAT_H
  2705. +#define MMAL_MSG_FORMAT_H
  2706. +
  2707. +#include "mmal-msg-common.h"
  2708. +
  2709. +/* MMAL_ES_FORMAT_T */
  2710. +
  2711. +
  2712. +struct mmal_audio_format {
  2713. + u32 channels; /**< Number of audio channels */
  2714. + u32 sample_rate; /**< Sample rate */
  2715. +
  2716. + u32 bits_per_sample; /**< Bits per sample */
  2717. + u32 block_align; /**< Size of a block of data */
  2718. +};
  2719. +
  2720. +struct mmal_video_format {
  2721. + u32 width; /**< Width of frame in pixels */
  2722. + u32 height; /**< Height of frame in rows of pixels */
  2723. + struct mmal_rect crop; /**< Visible region of the frame */
  2724. + struct mmal_rational frame_rate; /**< Frame rate */
  2725. + struct mmal_rational par; /**< Pixel aspect ratio */
  2726. +
  2727. + /* FourCC specifying the color space of the video stream. See the
  2728. + * \ref MmalColorSpace "pre-defined color spaces" for some examples.
  2729. + */
  2730. + u32 color_space;
  2731. +};
  2732. +
  2733. +struct mmal_subpicture_format {
  2734. + u32 x_offset;
  2735. + u32 y_offset;
  2736. +};
  2737. +
  2738. +union mmal_es_specific_format {
  2739. + struct mmal_audio_format audio;
  2740. + struct mmal_video_format video;
  2741. + struct mmal_subpicture_format subpicture;
  2742. +};
  2743. +
  2744. +/** Definition of an elementary stream format (MMAL_ES_FORMAT_T) */
  2745. +struct mmal_es_format {
  2746. + u32 type; /* enum mmal_es_type */
  2747. +
  2748. + u32 encoding; /* FourCC specifying encoding of the elementary stream.*/
  2749. + u32 encoding_variant; /* FourCC specifying the specific
  2750. + * encoding variant of the elementary
  2751. + * stream.
  2752. + */
  2753. +
  2754. + union mmal_es_specific_format *es; /* TODO: pointers in
  2755. + * message serialisation?!?
  2756. + */
  2757. + /* Type specific
  2758. + * information for the
  2759. + * elementary stream
  2760. + */
  2761. +
  2762. + u32 bitrate; /**< Bitrate in bits per second */
  2763. + u32 flags; /**< Flags describing properties of the elementary stream. */
  2764. +
  2765. + u32 extradata_size; /**< Size of the codec specific data */
  2766. + u8 *extradata; /**< Codec specific data */
  2767. +};
  2768. +
  2769. +#endif /* MMAL_MSG_FORMAT_H */
  2770. --- /dev/null
  2771. +++ b/drivers/media/platform/bcm2835/mmal-msg-port.h
  2772. @@ -0,0 +1,107 @@
  2773. +/*
  2774. + * Broadcom BM2835 V4L2 driver
  2775. + *
  2776. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  2777. + *
  2778. + * This file is subject to the terms and conditions of the GNU General Public
  2779. + * License. See the file COPYING in the main directory of this archive
  2780. + * for more details.
  2781. + *
  2782. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  2783. + * Dave Stevenson <dsteve@broadcom.com>
  2784. + * Simon Mellor <simellor@broadcom.com>
  2785. + * Luke Diamand <luked@broadcom.com>
  2786. + */
  2787. +
  2788. +/* MMAL_PORT_TYPE_T */
  2789. +enum mmal_port_type {
  2790. + MMAL_PORT_TYPE_UNKNOWN = 0, /**< Unknown port type */
  2791. + MMAL_PORT_TYPE_CONTROL, /**< Control port */
  2792. + MMAL_PORT_TYPE_INPUT, /**< Input port */
  2793. + MMAL_PORT_TYPE_OUTPUT, /**< Output port */
  2794. + MMAL_PORT_TYPE_CLOCK, /**< Clock port */
  2795. +};
  2796. +
  2797. +/** The port is pass-through and doesn't need buffer headers allocated */
  2798. +#define MMAL_PORT_CAPABILITY_PASSTHROUGH 0x01
  2799. +/** The port wants to allocate the buffer payloads.
  2800. + * This signals a preference that payload allocation should be done
  2801. + * on this port for efficiency reasons. */
  2802. +#define MMAL_PORT_CAPABILITY_ALLOCATION 0x02
  2803. +/** The port supports format change events.
  2804. + * This applies to input ports and is used to let the client know
  2805. + * whether the port supports being reconfigured via a format
  2806. + * change event (i.e. without having to disable the port). */
  2807. +#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE 0x04
  2808. +
  2809. +/* mmal port structure (MMAL_PORT_T)
  2810. + *
  2811. + * most elements are informational only, the pointer values for
  2812. + * interogation messages are generally provided as additional
  2813. + * strucures within the message. When used to set values only teh
  2814. + * buffer_num, buffer_size and userdata parameters are writable.
  2815. + */
  2816. +struct mmal_port {
  2817. + void *priv; /* Private member used by the framework */
  2818. + const char *name; /* Port name. Used for debugging purposes (RO) */
  2819. +
  2820. + u32 type; /* Type of the port (RO) enum mmal_port_type */
  2821. + u16 index; /* Index of the port in its type list (RO) */
  2822. + u16 index_all; /* Index of the port in the list of all ports (RO) */
  2823. +
  2824. + u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */
  2825. + struct mmal_es_format *format; /* Format of the elementary stream */
  2826. +
  2827. + u32 buffer_num_min; /* Minimum number of buffers the port
  2828. + * requires (RO). This is set by the
  2829. + * component.
  2830. + */
  2831. +
  2832. + u32 buffer_size_min; /* Minimum size of buffers the port
  2833. + * requires (RO). This is set by the
  2834. + * component.
  2835. + */
  2836. +
  2837. + u32 buffer_alignment_min; /* Minimum alignment requirement for
  2838. + * the buffers (RO). A value of
  2839. + * zero means no special alignment
  2840. + * requirements. This is set by the
  2841. + * component.
  2842. + */
  2843. +
  2844. + u32 buffer_num_recommended; /* Number of buffers the port
  2845. + * recommends for optimal
  2846. + * performance (RO). A value of
  2847. + * zero means no special
  2848. + * recommendation. This is set
  2849. + * by the component.
  2850. + */
  2851. +
  2852. + u32 buffer_size_recommended; /* Size of buffers the port
  2853. + * recommends for optimal
  2854. + * performance (RO). A value of
  2855. + * zero means no special
  2856. + * recommendation. This is set
  2857. + * by the component.
  2858. + */
  2859. +
  2860. + u32 buffer_num; /* Actual number of buffers the port will use.
  2861. + * This is set by the client.
  2862. + */
  2863. +
  2864. + u32 buffer_size; /* Actual maximum size of the buffers that
  2865. + * will be sent to the port. This is set by
  2866. + * the client.
  2867. + */
  2868. +
  2869. + void *component; /* Component this port belongs to (Read Only) */
  2870. +
  2871. + void *userdata; /* Field reserved for use by the client */
  2872. +
  2873. + u32 capabilities; /* Flags describing the capabilities of a
  2874. + * port (RO). Bitwise combination of \ref
  2875. + * portcapabilities "Port capabilities"
  2876. + * values.
  2877. + */
  2878. +
  2879. +};
  2880. --- /dev/null
  2881. +++ b/drivers/media/platform/bcm2835/mmal-msg.h
  2882. @@ -0,0 +1,404 @@
  2883. +/*
  2884. + * Broadcom BM2835 V4L2 driver
  2885. + *
  2886. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  2887. + *
  2888. + * This file is subject to the terms and conditions of the GNU General Public
  2889. + * License. See the file COPYING in the main directory of this archive
  2890. + * for more details.
  2891. + *
  2892. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  2893. + * Dave Stevenson <dsteve@broadcom.com>
  2894. + * Simon Mellor <simellor@broadcom.com>
  2895. + * Luke Diamand <luked@broadcom.com>
  2896. + */
  2897. +
  2898. +/* all the data structures which serialise the MMAL protocol. note
  2899. + * these are directly mapped onto the recived message data.
  2900. + *
  2901. + * BEWARE: They seem to *assume* pointers are u32 and that there is no
  2902. + * structure padding!
  2903. + *
  2904. + * NOTE: this implementation uses kernel types to ensure sizes. Rather
  2905. + * than assigning values to enums to force their size the
  2906. + * implementation uses fixed size types and not the enums (though the
  2907. + * comments have the actual enum type
  2908. + */
  2909. +
  2910. +#define VC_MMAL_VER 15
  2911. +#define VC_MMAL_MIN_VER 10
  2912. +#define VC_MMAL_SERVER_NAME MAKE_FOURCC("mmal")
  2913. +
  2914. +/* max total message size is 512 bytes */
  2915. +#define MMAL_MSG_MAX_SIZE 512
  2916. +/* with six 32bit header elements max payload is therefore 488 bytes */
  2917. +#define MMAL_MSG_MAX_PAYLOAD 488
  2918. +
  2919. +#include "mmal-msg-common.h"
  2920. +#include "mmal-msg-format.h"
  2921. +#include "mmal-msg-port.h"
  2922. +
  2923. +enum mmal_msg_type {
  2924. + MMAL_MSG_TYPE_QUIT = 1,
  2925. + MMAL_MSG_TYPE_SERVICE_CLOSED,
  2926. + MMAL_MSG_TYPE_GET_VERSION,
  2927. + MMAL_MSG_TYPE_COMPONENT_CREATE,
  2928. + MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */
  2929. + MMAL_MSG_TYPE_COMPONENT_ENABLE,
  2930. + MMAL_MSG_TYPE_COMPONENT_DISABLE,
  2931. + MMAL_MSG_TYPE_PORT_INFO_GET,
  2932. + MMAL_MSG_TYPE_PORT_INFO_SET,
  2933. + MMAL_MSG_TYPE_PORT_ACTION, /* 10 */
  2934. + MMAL_MSG_TYPE_BUFFER_FROM_HOST,
  2935. + MMAL_MSG_TYPE_BUFFER_TO_HOST,
  2936. + MMAL_MSG_TYPE_GET_STATS,
  2937. + MMAL_MSG_TYPE_PORT_PARAMETER_SET,
  2938. + MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */
  2939. + MMAL_MSG_TYPE_EVENT_TO_HOST,
  2940. + MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT,
  2941. + MMAL_MSG_TYPE_OPAQUE_ALLOCATOR,
  2942. + MMAL_MSG_TYPE_CONSUME_MEM,
  2943. + MMAL_MSG_TYPE_LMK, /* 20 */
  2944. + MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC,
  2945. + MMAL_MSG_TYPE_DRM_GET_LHS32,
  2946. + MMAL_MSG_TYPE_DRM_GET_TIME,
  2947. + MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN,
  2948. + MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */
  2949. + MMAL_MSG_TYPE_HOST_LOG,
  2950. + MMAL_MSG_TYPE_MSG_LAST
  2951. +};
  2952. +
  2953. +/* port action request messages differ depending on the action type */
  2954. +enum mmal_msg_port_action_type {
  2955. + MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0, /* Unkown action */
  2956. + MMAL_MSG_PORT_ACTION_TYPE_ENABLE, /* Enable a port */
  2957. + MMAL_MSG_PORT_ACTION_TYPE_DISABLE, /* Disable a port */
  2958. + MMAL_MSG_PORT_ACTION_TYPE_FLUSH, /* Flush a port */
  2959. + MMAL_MSG_PORT_ACTION_TYPE_CONNECT, /* Connect ports */
  2960. + MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, /* Disconnect ports */
  2961. + MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/
  2962. +};
  2963. +
  2964. +struct mmal_msg_header {
  2965. + u32 magic;
  2966. + u32 type; /** enum mmal_msg_type */
  2967. +
  2968. + /* Opaque handle to the control service */
  2969. + struct mmal_control_service *control_service;
  2970. +
  2971. + struct mmal_msg_context *context; /** a u32 per message context */
  2972. + u32 status; /** The status of the vchiq operation */
  2973. + u32 padding;
  2974. +};
  2975. +
  2976. +/* Send from VC to host to report version */
  2977. +struct mmal_msg_version {
  2978. + u32 flags;
  2979. + u32 major;
  2980. + u32 minor;
  2981. + u32 minimum;
  2982. +};
  2983. +
  2984. +/* request to VC to create component */
  2985. +struct mmal_msg_component_create {
  2986. + void *client_component; /* component context */
  2987. + char name[128];
  2988. + u32 pid; /* For debug */
  2989. +};
  2990. +
  2991. +/* reply from VC to component creation request */
  2992. +struct mmal_msg_component_create_reply {
  2993. + u32 status; /** enum mmal_msg_status - how does this differ to
  2994. + * the one in the header?
  2995. + */
  2996. + u32 component_handle; /* VideoCore handle for component */
  2997. + u32 input_num; /* Number of input ports */
  2998. + u32 output_num; /* Number of output ports */
  2999. + u32 clock_num; /* Number of clock ports */
  3000. +};
  3001. +
  3002. +/* request to VC to destroy a component */
  3003. +struct mmal_msg_component_destroy {
  3004. + u32 component_handle;
  3005. +};
  3006. +
  3007. +struct mmal_msg_component_destroy_reply {
  3008. + u32 status; /** The component destruction status */
  3009. +};
  3010. +
  3011. +
  3012. +/* request and reply to VC to enable a component */
  3013. +struct mmal_msg_component_enable {
  3014. + u32 component_handle;
  3015. +};
  3016. +
  3017. +struct mmal_msg_component_enable_reply {
  3018. + u32 status; /** The component enable status */
  3019. +};
  3020. +
  3021. +
  3022. +/* request and reply to VC to disable a component */
  3023. +struct mmal_msg_component_disable {
  3024. + u32 component_handle;
  3025. +};
  3026. +
  3027. +struct mmal_msg_component_disable_reply {
  3028. + u32 status; /** The component disable status */
  3029. +};
  3030. +
  3031. +/* request to VC to get port information */
  3032. +struct mmal_msg_port_info_get {
  3033. + u32 component_handle; /* component handle port is associated with */
  3034. + u32 port_type; /* enum mmal_msg_port_type */
  3035. + u32 index; /* port index to query */
  3036. +};
  3037. +
  3038. +/* reply from VC to get port info request */
  3039. +struct mmal_msg_port_info_get_reply {
  3040. + u32 status; /** enum mmal_msg_status */
  3041. + u32 component_handle; /* component handle port is associated with */
  3042. + u32 port_type; /* enum mmal_msg_port_type */
  3043. + u32 port_index; /* port indexed in query */
  3044. + s32 found; /* unused */
  3045. + u32 port_handle; /**< Handle to use for this port */
  3046. + struct mmal_port port;
  3047. + struct mmal_es_format format; /* elementry stream format */
  3048. + union mmal_es_specific_format es; /* es type specific data */
  3049. + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */
  3050. +};
  3051. +
  3052. +/* request to VC to set port information */
  3053. +struct mmal_msg_port_info_set {
  3054. + u32 component_handle;
  3055. + u32 port_type; /* enum mmal_msg_port_type */
  3056. + u32 port_index; /* port indexed in query */
  3057. + struct mmal_port port;
  3058. + struct mmal_es_format format;
  3059. + union mmal_es_specific_format es;
  3060. + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
  3061. +};
  3062. +
  3063. +/* reply from VC to port info set request */
  3064. +struct mmal_msg_port_info_set_reply {
  3065. + u32 status;
  3066. + u32 component_handle; /* component handle port is associated with */
  3067. + u32 port_type; /* enum mmal_msg_port_type */
  3068. + u32 index; /* port indexed in query */
  3069. + s32 found; /* unused */
  3070. + u32 port_handle; /**< Handle to use for this port */
  3071. + struct mmal_port port;
  3072. + struct mmal_es_format format;
  3073. + union mmal_es_specific_format es;
  3074. + u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE];
  3075. +};
  3076. +
  3077. +
  3078. +/* port action requests that take a mmal_port as a parameter */
  3079. +struct mmal_msg_port_action_port {
  3080. + u32 component_handle;
  3081. + u32 port_handle;
  3082. + u32 action; /* enum mmal_msg_port_action_type */
  3083. + struct mmal_port port;
  3084. +};
  3085. +
  3086. +/* port action requests that take handles as a parameter */
  3087. +struct mmal_msg_port_action_handle {
  3088. + u32 component_handle;
  3089. + u32 port_handle;
  3090. + u32 action; /* enum mmal_msg_port_action_type */
  3091. + u32 connect_component_handle;
  3092. + u32 connect_port_handle;
  3093. +};
  3094. +
  3095. +struct mmal_msg_port_action_reply {
  3096. + u32 status; /** The port action operation status */
  3097. +};
  3098. +
  3099. +
  3100. +
  3101. +
  3102. +/* MMAL buffer transfer */
  3103. +
  3104. +/** Size of space reserved in a buffer message for short messages. */
  3105. +#define MMAL_VC_SHORT_DATA 128
  3106. +
  3107. +/** Signals that the current payload is the end of the stream of data */
  3108. +#define MMAL_BUFFER_HEADER_FLAG_EOS (1<<0)
  3109. +/** Signals that the start of the current payload starts a frame */
  3110. +#define MMAL_BUFFER_HEADER_FLAG_FRAME_START (1<<1)
  3111. +/** Signals that the end of the current payload ends a frame */
  3112. +#define MMAL_BUFFER_HEADER_FLAG_FRAME_END (1<<2)
  3113. +/** Signals that the current payload contains only complete frames (>1) */
  3114. +#define MMAL_BUFFER_HEADER_FLAG_FRAME \
  3115. + (MMAL_BUFFER_HEADER_FLAG_FRAME_START|MMAL_BUFFER_HEADER_FLAG_FRAME_END)
  3116. +/** Signals that the current payload is a keyframe (i.e. self decodable) */
  3117. +#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME (1<<3)
  3118. +/** Signals a discontinuity in the stream of data (e.g. after a seek).
  3119. + * Can be used for instance by a decoder to reset its state */
  3120. +#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY (1<<4)
  3121. +/** Signals a buffer containing some kind of config data for the component
  3122. + * (e.g. codec config data) */
  3123. +#define MMAL_BUFFER_HEADER_FLAG_CONFIG (1<<5)
  3124. +/** Signals an encrypted payload */
  3125. +#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED (1<<6)
  3126. +/** Signals a buffer containing side information */
  3127. +#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO (1<<7)
  3128. +/** Signals a buffer which is the snapshot/postview image from a stills
  3129. + * capture
  3130. + */
  3131. +#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT (1<<8)
  3132. +/** Signals a buffer which contains data known to be corrupted */
  3133. +#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED (1<<9)
  3134. +/** Signals that a buffer failed to be transmitted */
  3135. +#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED (1<<10)
  3136. +
  3137. +struct mmal_driver_buffer {
  3138. + u32 magic;
  3139. + u32 component_handle;
  3140. + u32 port_handle;
  3141. + void *client_context;
  3142. +};
  3143. +
  3144. +/* buffer header */
  3145. +struct mmal_buffer_header {
  3146. + struct mmal_buffer_header *next; /* next header */
  3147. + void *priv; /* framework private data */
  3148. + u32 cmd;
  3149. + void *data;
  3150. + u32 alloc_size;
  3151. + u32 length;
  3152. + u32 offset;
  3153. + u32 flags;
  3154. + s64 pts;
  3155. + s64 dts;
  3156. + void *type;
  3157. + void *user_data;
  3158. +};
  3159. +
  3160. +struct mmal_buffer_header_type_specific {
  3161. + union {
  3162. + struct {
  3163. + u32 planes;
  3164. + u32 offset[4];
  3165. + u32 pitch[4];
  3166. + u32 flags;
  3167. + } video;
  3168. + } u;
  3169. +};
  3170. +
  3171. +struct mmal_msg_buffer_from_host {
  3172. + /* The front 32 bytes of the buffer header are copied
  3173. + * back to us in the reply to allow for context. This
  3174. + * area is used to store two mmal_driver_buffer structures to
  3175. + * allow for multiple concurrent service users.
  3176. + */
  3177. + /* control data */
  3178. + struct mmal_driver_buffer drvbuf;
  3179. +
  3180. + /* referenced control data for passthrough buffer management */
  3181. + struct mmal_driver_buffer drvbuf_ref;
  3182. + struct mmal_buffer_header buffer_header; /* buffer header itself */
  3183. + struct mmal_buffer_header_type_specific buffer_header_type_specific;
  3184. + s32 is_zero_copy;
  3185. + s32 has_reference;
  3186. +
  3187. + /** allows short data to be xfered in control message */
  3188. + u32 payload_in_message;
  3189. + u8 short_data[MMAL_VC_SHORT_DATA];
  3190. +};
  3191. +
  3192. +
  3193. +/* port parameter setting */
  3194. +
  3195. +#define MMAL_WORKER_PORT_PARAMETER_SPACE 96
  3196. +
  3197. +struct mmal_msg_port_parameter_set {
  3198. + u32 component_handle; /* component */
  3199. + u32 port_handle; /* port */
  3200. + u32 id; /* Parameter ID */
  3201. + u32 size; /* Parameter size */
  3202. + uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
  3203. +};
  3204. +
  3205. +struct mmal_msg_port_parameter_set_reply {
  3206. + u32 status; /** enum mmal_msg_status todo: how does this
  3207. + * differ to the one in the header?
  3208. + */
  3209. +};
  3210. +
  3211. +/* port parameter getting */
  3212. +
  3213. +struct mmal_msg_port_parameter_get {
  3214. + u32 component_handle; /* component */
  3215. + u32 port_handle; /* port */
  3216. + u32 id; /* Parameter ID */
  3217. + u32 size; /* Parameter size */
  3218. +};
  3219. +
  3220. +struct mmal_msg_port_parameter_get_reply {
  3221. + u32 status; /* Status of mmal_port_parameter_get call */
  3222. + u32 id; /* Parameter ID */
  3223. + u32 size; /* Parameter size */
  3224. + uint32_t value[MMAL_WORKER_PORT_PARAMETER_SPACE];
  3225. +};
  3226. +
  3227. +/* event messages */
  3228. +#define MMAL_WORKER_EVENT_SPACE 256
  3229. +
  3230. +struct mmal_msg_event_to_host {
  3231. + void *client_component; /* component context */
  3232. +
  3233. + u32 port_type;
  3234. + u32 port_num;
  3235. +
  3236. + u32 cmd;
  3237. + u32 length;
  3238. + u8 data[MMAL_WORKER_EVENT_SPACE];
  3239. + struct mmal_buffer_header *delayed_buffer;
  3240. +};
  3241. +
  3242. +/* all mmal messages are serialised through this structure */
  3243. +struct mmal_msg {
  3244. + /* header */
  3245. + struct mmal_msg_header h;
  3246. + /* payload */
  3247. + union {
  3248. + struct mmal_msg_version version;
  3249. +
  3250. + struct mmal_msg_component_create component_create;
  3251. + struct mmal_msg_component_create_reply component_create_reply;
  3252. +
  3253. + struct mmal_msg_component_destroy component_destroy;
  3254. + struct mmal_msg_component_destroy_reply component_destroy_reply;
  3255. +
  3256. + struct mmal_msg_component_enable component_enable;
  3257. + struct mmal_msg_component_enable_reply component_enable_reply;
  3258. +
  3259. + struct mmal_msg_component_disable component_disable;
  3260. + struct mmal_msg_component_disable_reply component_disable_reply;
  3261. +
  3262. + struct mmal_msg_port_info_get port_info_get;
  3263. + struct mmal_msg_port_info_get_reply port_info_get_reply;
  3264. +
  3265. + struct mmal_msg_port_info_set port_info_set;
  3266. + struct mmal_msg_port_info_set_reply port_info_set_reply;
  3267. +
  3268. + struct mmal_msg_port_action_port port_action_port;
  3269. + struct mmal_msg_port_action_handle port_action_handle;
  3270. + struct mmal_msg_port_action_reply port_action_reply;
  3271. +
  3272. + struct mmal_msg_buffer_from_host buffer_from_host;
  3273. +
  3274. + struct mmal_msg_port_parameter_set port_parameter_set;
  3275. + struct mmal_msg_port_parameter_set_reply
  3276. + port_parameter_set_reply;
  3277. + struct mmal_msg_port_parameter_get
  3278. + port_parameter_get;
  3279. + struct mmal_msg_port_parameter_get_reply
  3280. + port_parameter_get_reply;
  3281. +
  3282. + struct mmal_msg_event_to_host event_to_host;
  3283. +
  3284. + u8 payload[MMAL_MSG_MAX_PAYLOAD];
  3285. + } u;
  3286. +};
  3287. --- /dev/null
  3288. +++ b/drivers/media/platform/bcm2835/mmal-parameters.h
  3289. @@ -0,0 +1,539 @@
  3290. +/*
  3291. + * Broadcom BM2835 V4L2 driver
  3292. + *
  3293. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  3294. + *
  3295. + * This file is subject to the terms and conditions of the GNU General Public
  3296. + * License. See the file COPYING in the main directory of this archive
  3297. + * for more details.
  3298. + *
  3299. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  3300. + * Dave Stevenson <dsteve@broadcom.com>
  3301. + * Simon Mellor <simellor@broadcom.com>
  3302. + * Luke Diamand <luked@broadcom.com>
  3303. + */
  3304. +
  3305. +/* common parameters */
  3306. +
  3307. +/** @name Parameter groups
  3308. + * Parameters are divided into groups, and then allocated sequentially within
  3309. + * a group using an enum.
  3310. + * @{
  3311. + */
  3312. +
  3313. +/** Common parameter ID group, used with many types of component. */
  3314. +#define MMAL_PARAMETER_GROUP_COMMON (0<<16)
  3315. +/** Camera-specific parameter ID group. */
  3316. +#define MMAL_PARAMETER_GROUP_CAMERA (1<<16)
  3317. +/** Video-specific parameter ID group. */
  3318. +#define MMAL_PARAMETER_GROUP_VIDEO (2<<16)
  3319. +/** Audio-specific parameter ID group. */
  3320. +#define MMAL_PARAMETER_GROUP_AUDIO (3<<16)
  3321. +/** Clock-specific parameter ID group. */
  3322. +#define MMAL_PARAMETER_GROUP_CLOCK (4<<16)
  3323. +/** Miracast-specific parameter ID group. */
  3324. +#define MMAL_PARAMETER_GROUP_MIRACAST (5<<16)
  3325. +
  3326. +/* Common parameters */
  3327. +enum mmal_parameter_common_type {
  3328. + MMAL_PARAMETER_UNUSED /**< Never a valid parameter ID */
  3329. + = MMAL_PARAMETER_GROUP_COMMON,
  3330. + MMAL_PARAMETER_SUPPORTED_ENCODINGS, /**< MMAL_PARAMETER_ENCODING_T */
  3331. + MMAL_PARAMETER_URI, /**< MMAL_PARAMETER_URI_T */
  3332. +
  3333. + /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */
  3334. + MMAL_PARAMETER_CHANGE_EVENT_REQUEST,
  3335. +
  3336. + /** MMAL_PARAMETER_BOOLEAN_T */
  3337. + MMAL_PARAMETER_ZERO_COPY,
  3338. +
  3339. + /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */
  3340. + MMAL_PARAMETER_BUFFER_REQUIREMENTS,
  3341. +
  3342. + MMAL_PARAMETER_STATISTICS, /**< MMAL_PARAMETER_STATISTICS_T */
  3343. + MMAL_PARAMETER_CORE_STATISTICS, /**< MMAL_PARAMETER_CORE_STATISTICS_T */
  3344. + MMAL_PARAMETER_MEM_USAGE, /**< MMAL_PARAMETER_MEM_USAGE_T */
  3345. + MMAL_PARAMETER_BUFFER_FLAG_FILTER, /**< MMAL_PARAMETER_UINT32_T */
  3346. + MMAL_PARAMETER_SEEK, /**< MMAL_PARAMETER_SEEK_T */
  3347. + MMAL_PARAMETER_POWERMON_ENABLE, /**< MMAL_PARAMETER_BOOLEAN_T */
  3348. + MMAL_PARAMETER_LOGGING, /**< MMAL_PARAMETER_LOGGING_T */
  3349. + MMAL_PARAMETER_SYSTEM_TIME /**< MMAL_PARAMETER_UINT64_T */
  3350. +};
  3351. +
  3352. +/* camera parameters */
  3353. +
  3354. +enum mmal_parameter_camera_type {
  3355. + /* 0 */
  3356. + /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */
  3357. + MMAL_PARAMETER_THUMBNAIL_CONFIGURATION
  3358. + = MMAL_PARAMETER_GROUP_CAMERA,
  3359. + MMAL_PARAMETER_CAPTURE_QUALITY, /**< Unused? */
  3360. + MMAL_PARAMETER_ROTATION, /**< @ref MMAL_PARAMETER_INT32_T */
  3361. + MMAL_PARAMETER_EXIF_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3362. + MMAL_PARAMETER_EXIF, /**< @ref MMAL_PARAMETER_EXIF_T */
  3363. + MMAL_PARAMETER_AWB_MODE, /**< @ref MMAL_PARAM_AWBMODE_T */
  3364. + MMAL_PARAMETER_IMAGE_EFFECT, /**< @ref MMAL_PARAMETER_IMAGEFX_T */
  3365. + MMAL_PARAMETER_COLOUR_EFFECT, /**< @ref MMAL_PARAMETER_COLOURFX_T */
  3366. + MMAL_PARAMETER_FLICKER_AVOID, /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */
  3367. + MMAL_PARAMETER_FLASH, /**< @ref MMAL_PARAMETER_FLASH_T */
  3368. + MMAL_PARAMETER_REDEYE, /**< @ref MMAL_PARAMETER_REDEYE_T */
  3369. + MMAL_PARAMETER_FOCUS, /**< @ref MMAL_PARAMETER_FOCUS_T */
  3370. + MMAL_PARAMETER_FOCAL_LENGTHS, /**< Unused? */
  3371. + MMAL_PARAMETER_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
  3372. + MMAL_PARAMETER_ZOOM, /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */
  3373. + MMAL_PARAMETER_MIRROR, /**< @ref MMAL_PARAMETER_MIRROR_T */
  3374. +
  3375. + /* 0x10 */
  3376. + MMAL_PARAMETER_CAMERA_NUM, /**< @ref MMAL_PARAMETER_UINT32_T */
  3377. + MMAL_PARAMETER_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3378. + MMAL_PARAMETER_EXPOSURE_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */
  3379. + MMAL_PARAMETER_EXP_METERING_MODE, /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */
  3380. + MMAL_PARAMETER_FOCUS_STATUS, /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */
  3381. + MMAL_PARAMETER_CAMERA_CONFIG, /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */
  3382. + MMAL_PARAMETER_CAPTURE_STATUS, /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */
  3383. + MMAL_PARAMETER_FACE_TRACK, /**< @ref MMAL_PARAMETER_FACE_TRACK_T */
  3384. + MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3385. + MMAL_PARAMETER_JPEG_Q_FACTOR, /**< @ref MMAL_PARAMETER_UINT32_T */
  3386. + MMAL_PARAMETER_FRAME_RATE, /**< @ref MMAL_PARAMETER_FRAME_RATE_T */
  3387. + MMAL_PARAMETER_USE_STC, /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */
  3388. + MMAL_PARAMETER_CAMERA_INFO, /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */
  3389. + MMAL_PARAMETER_VIDEO_STABILISATION, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3390. + MMAL_PARAMETER_FACE_TRACK_RESULTS, /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */
  3391. + MMAL_PARAMETER_ENABLE_RAW_CAPTURE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3392. +
  3393. + /* 0x20 */
  3394. + MMAL_PARAMETER_DPF_FILE, /**< @ref MMAL_PARAMETER_URI_T */
  3395. + MMAL_PARAMETER_ENABLE_DPF_FILE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3396. + MMAL_PARAMETER_DPF_FAIL_IS_FATAL, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3397. + MMAL_PARAMETER_CAPTURE_MODE, /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */
  3398. + MMAL_PARAMETER_FOCUS_REGIONS, /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */
  3399. + MMAL_PARAMETER_INPUT_CROP, /**< @ref MMAL_PARAMETER_INPUT_CROP_T */
  3400. + MMAL_PARAMETER_SENSOR_INFORMATION, /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */
  3401. + MMAL_PARAMETER_FLASH_SELECT, /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */
  3402. + MMAL_PARAMETER_FIELD_OF_VIEW, /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */
  3403. + MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3404. + MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, /**< @ref MMAL_PARAMETER_DRC_T */
  3405. + MMAL_PARAMETER_ALGORITHM_CONTROL, /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */
  3406. + MMAL_PARAMETER_SHARPNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
  3407. + MMAL_PARAMETER_CONTRAST, /**< @ref MMAL_PARAMETER_RATIONAL_T */
  3408. + MMAL_PARAMETER_BRIGHTNESS, /**< @ref MMAL_PARAMETER_RATIONAL_T */
  3409. + MMAL_PARAMETER_SATURATION, /**< @ref MMAL_PARAMETER_RATIONAL_T */
  3410. +
  3411. + /* 0x30 */
  3412. + MMAL_PARAMETER_ISO, /**< @ref MMAL_PARAMETER_UINT32_T */
  3413. + MMAL_PARAMETER_ANTISHAKE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3414. +
  3415. + /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */
  3416. + MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS,
  3417. +
  3418. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3419. + MMAL_PARAMETER_CAMERA_BURST_CAPTURE,
  3420. +
  3421. + /** @ref MMAL_PARAMETER_UINT32_T */
  3422. + MMAL_PARAMETER_CAMERA_MIN_ISO,
  3423. +
  3424. + /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */
  3425. + MMAL_PARAMETER_CAMERA_USE_CASE,
  3426. +
  3427. + /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3428. + MMAL_PARAMETER_CAPTURE_STATS_PASS,
  3429. +
  3430. + /** @ref MMAL_PARAMETER_UINT32_T */
  3431. + MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG,
  3432. +
  3433. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3434. + MMAL_PARAMETER_ENABLE_REGISTER_FILE,
  3435. +
  3436. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3437. + MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL,
  3438. +
  3439. + /** @ref MMAL_PARAMETER_CONFIGFILE_T */
  3440. + MMAL_PARAMETER_CONFIGFILE_REGISTERS,
  3441. +
  3442. + /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */
  3443. + MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS,
  3444. + MMAL_PARAMETER_JPEG_ATTACH_LOG, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3445. + MMAL_PARAMETER_ZERO_SHUTTER_LAG, /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */
  3446. + MMAL_PARAMETER_FPS_RANGE, /**< @ref MMAL_PARAMETER_FPS_RANGE_T */
  3447. + MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, /**< @ref MMAL_PARAMETER_INT32_T */
  3448. +
  3449. + /* 0x40 */
  3450. + MMAL_PARAMETER_SW_SHARPEN_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3451. + MMAL_PARAMETER_FLASH_REQUIRED, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3452. + MMAL_PARAMETER_SW_SATURATION_DISABLE, /**< @ref MMAL_PARAMETER_BOOLEAN_T */
  3453. +};
  3454. +
  3455. +enum mmal_parameter_camera_config_timestamp_mode {
  3456. + MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */
  3457. + MMAL_PARAM_TIMESTAMP_MODE_RAW_STC, /* Use the raw STC value
  3458. + * for the frame timestamp
  3459. + */
  3460. + MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp
  3461. + * but subtract the
  3462. + * timestamp of the first
  3463. + * frame sent to give a
  3464. + * zero based timestamp.
  3465. + */
  3466. +};
  3467. +
  3468. +/* camera configuration parameter */
  3469. +struct mmal_parameter_camera_config {
  3470. + /* Parameters for setting up the image pools */
  3471. + u32 max_stills_w; /* Max size of stills capture */
  3472. + u32 max_stills_h;
  3473. + u32 stills_yuv422; /* Allow YUV422 stills capture */
  3474. + u32 one_shot_stills; /* Continuous or one shot stills captures. */
  3475. +
  3476. + u32 max_preview_video_w; /* Max size of the preview or video
  3477. + * capture frames
  3478. + */
  3479. + u32 max_preview_video_h;
  3480. + u32 num_preview_video_frames;
  3481. +
  3482. + /** Sets the height of the circular buffer for stills capture. */
  3483. + u32 stills_capture_circular_buffer_height;
  3484. +
  3485. + /** Allows preview/encode to resume as fast as possible after the stills
  3486. + * input frame has been received, and then processes the still frame in
  3487. + * the background whilst preview/encode has resumed.
  3488. + * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE.
  3489. + */
  3490. + u32 fast_preview_resume;
  3491. +
  3492. + /** Selects algorithm for timestamping frames if
  3493. + * there is no clock component connected.
  3494. + * enum mmal_parameter_camera_config_timestamp_mode
  3495. + */
  3496. + s32 use_stc_timestamp;
  3497. +};
  3498. +
  3499. +
  3500. +enum mmal_parameter_exposuremode {
  3501. + MMAL_PARAM_EXPOSUREMODE_OFF,
  3502. + MMAL_PARAM_EXPOSUREMODE_AUTO,
  3503. + MMAL_PARAM_EXPOSUREMODE_NIGHT,
  3504. + MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW,
  3505. + MMAL_PARAM_EXPOSUREMODE_BACKLIGHT,
  3506. + MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT,
  3507. + MMAL_PARAM_EXPOSUREMODE_SPORTS,
  3508. + MMAL_PARAM_EXPOSUREMODE_SNOW,
  3509. + MMAL_PARAM_EXPOSUREMODE_BEACH,
  3510. + MMAL_PARAM_EXPOSUREMODE_VERYLONG,
  3511. + MMAL_PARAM_EXPOSUREMODE_FIXEDFPS,
  3512. + MMAL_PARAM_EXPOSUREMODE_ANTISHAKE,
  3513. + MMAL_PARAM_EXPOSUREMODE_FIREWORKS,
  3514. +};
  3515. +
  3516. +enum mmal_parameter_exposuremeteringmode {
  3517. + MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE,
  3518. + MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT,
  3519. + MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT,
  3520. + MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX,
  3521. +};
  3522. +
  3523. +enum mmal_parameter_awbmode {
  3524. + MMAL_PARAM_AWBMODE_OFF,
  3525. + MMAL_PARAM_AWBMODE_AUTO,
  3526. + MMAL_PARAM_AWBMODE_SUNLIGHT,
  3527. + MMAL_PARAM_AWBMODE_CLOUDY,
  3528. + MMAL_PARAM_AWBMODE_SHADE,
  3529. + MMAL_PARAM_AWBMODE_TUNGSTEN,
  3530. + MMAL_PARAM_AWBMODE_FLUORESCENT,
  3531. + MMAL_PARAM_AWBMODE_INCANDESCENT,
  3532. + MMAL_PARAM_AWBMODE_FLASH,
  3533. + MMAL_PARAM_AWBMODE_HORIZON,
  3534. +};
  3535. +
  3536. +enum mmal_parameter_imagefx {
  3537. + MMAL_PARAM_IMAGEFX_NONE,
  3538. + MMAL_PARAM_IMAGEFX_NEGATIVE,
  3539. + MMAL_PARAM_IMAGEFX_SOLARIZE,
  3540. + MMAL_PARAM_IMAGEFX_POSTERIZE,
  3541. + MMAL_PARAM_IMAGEFX_WHITEBOARD,
  3542. + MMAL_PARAM_IMAGEFX_BLACKBOARD,
  3543. + MMAL_PARAM_IMAGEFX_SKETCH,
  3544. + MMAL_PARAM_IMAGEFX_DENOISE,
  3545. + MMAL_PARAM_IMAGEFX_EMBOSS,
  3546. + MMAL_PARAM_IMAGEFX_OILPAINT,
  3547. + MMAL_PARAM_IMAGEFX_HATCH,
  3548. + MMAL_PARAM_IMAGEFX_GPEN,
  3549. + MMAL_PARAM_IMAGEFX_PASTEL,
  3550. + MMAL_PARAM_IMAGEFX_WATERCOLOUR,
  3551. + MMAL_PARAM_IMAGEFX_FILM,
  3552. + MMAL_PARAM_IMAGEFX_BLUR,
  3553. + MMAL_PARAM_IMAGEFX_SATURATION,
  3554. + MMAL_PARAM_IMAGEFX_COLOURSWAP,
  3555. + MMAL_PARAM_IMAGEFX_WASHEDOUT,
  3556. + MMAL_PARAM_IMAGEFX_POSTERISE,
  3557. + MMAL_PARAM_IMAGEFX_COLOURPOINT,
  3558. + MMAL_PARAM_IMAGEFX_COLOURBALANCE,
  3559. + MMAL_PARAM_IMAGEFX_CARTOON,
  3560. +};
  3561. +
  3562. +/** Manner of video rate control */
  3563. +enum mmal_parameter_rate_control_mode {
  3564. + MMAL_VIDEO_RATECONTROL_DEFAULT,
  3565. + MMAL_VIDEO_RATECONTROL_VARIABLE,
  3566. + MMAL_VIDEO_RATECONTROL_CONSTANT,
  3567. + MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES,
  3568. + MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES
  3569. +};
  3570. +
  3571. +/* video parameters */
  3572. +
  3573. +enum mmal_parameter_video_type {
  3574. + /** @ref MMAL_DISPLAYREGION_T */
  3575. + MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO,
  3576. +
  3577. + /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
  3578. + MMAL_PARAMETER_SUPPORTED_PROFILES,
  3579. +
  3580. + /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */
  3581. + MMAL_PARAMETER_PROFILE,
  3582. +
  3583. + /** @ref MMAL_PARAMETER_UINT32_T */
  3584. + MMAL_PARAMETER_INTRAPERIOD,
  3585. +
  3586. + /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */
  3587. + MMAL_PARAMETER_RATECONTROL,
  3588. +
  3589. + /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */
  3590. + MMAL_PARAMETER_NALUNITFORMAT,
  3591. +
  3592. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3593. + MMAL_PARAMETER_MINIMISE_FRAGMENTATION,
  3594. +
  3595. + /** @ref MMAL_PARAMETER_UINT32_T.
  3596. + * Setting the value to zero resets to the default (one slice per frame).
  3597. + */
  3598. + MMAL_PARAMETER_MB_ROWS_PER_SLICE,
  3599. +
  3600. + /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */
  3601. + MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION,
  3602. +
  3603. + /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */
  3604. + MMAL_PARAMETER_VIDEO_EEDE_ENABLE,
  3605. +
  3606. + /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */
  3607. + MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE,
  3608. +
  3609. + /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */
  3610. + MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME,
  3611. + /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */
  3612. + MMAL_PARAMETER_VIDEO_INTRA_REFRESH,
  3613. +
  3614. + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
  3615. + MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT,
  3616. +
  3617. + /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */
  3618. + MMAL_PARAMETER_VIDEO_BIT_RATE,
  3619. +
  3620. + /** @ref MMAL_PARAMETER_FRAME_RATE_T */
  3621. + MMAL_PARAMETER_VIDEO_FRAME_RATE,
  3622. +
  3623. + /** @ref MMAL_PARAMETER_UINT32_T. */
  3624. + MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT,
  3625. +
  3626. + /** @ref MMAL_PARAMETER_UINT32_T. */
  3627. + MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT,
  3628. +
  3629. + /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */
  3630. + MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL,
  3631. +
  3632. + MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */
  3633. + /** @ref MMAL_PARAMETER_UINT32_T.
  3634. + * Changing this parameter from the default can reduce frame rate
  3635. + * because image buffers need to be re-pitched.
  3636. + */
  3637. + MMAL_PARAMETER_VIDEO_ALIGN_HORIZ,
  3638. +
  3639. + /** @ref MMAL_PARAMETER_UINT32_T.
  3640. + * Changing this parameter from the default can reduce frame rate
  3641. + * because image buffers need to be re-pitched.
  3642. + */
  3643. + MMAL_PARAMETER_VIDEO_ALIGN_VERT,
  3644. +
  3645. + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
  3646. + MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES,
  3647. +
  3648. + /** @ref MMAL_PARAMETER_UINT32_T. */
  3649. + MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT,
  3650. +
  3651. + /**< @ref MMAL_PARAMETER_UINT32_T. */
  3652. + MMAL_PARAMETER_VIDEO_ENCODE_QP_P,
  3653. +
  3654. + /**< @ref MMAL_PARAMETER_UINT32_T. */
  3655. + MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT,
  3656. +
  3657. + /** @ref MMAL_PARAMETER_UINT32_T */
  3658. + MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS,
  3659. +
  3660. + /** @ref MMAL_PARAMETER_UINT32_T. */
  3661. + MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE,
  3662. +
  3663. + /* H264 specific parameters */
  3664. +
  3665. + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
  3666. + MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC,
  3667. +
  3668. + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
  3669. + MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY,
  3670. +
  3671. + /** @ref MMAL_PARAMETER_BOOLEAN_T. */
  3672. + MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS,
  3673. +
  3674. + /** @ref MMAL_PARAMETER_UINT32_T. */
  3675. + MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC,
  3676. +
  3677. + /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */
  3678. + MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE,
  3679. +
  3680. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3681. + MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN,
  3682. +
  3683. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3684. + MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP,
  3685. +
  3686. + /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */
  3687. + MMAL_PARAMETER_VIDEO_DRM_INIT_INFO,
  3688. +
  3689. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3690. + MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO,
  3691. +
  3692. + /** @ref MMAL_PARAMETER_BOOLEAN_T */
  3693. + MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT,
  3694. +
  3695. + /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */
  3696. + MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER,
  3697. +
  3698. + /** @ref MMAL_PARAMETER_BYTES_T */
  3699. + MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3
  3700. +};
  3701. +
  3702. +/** Valid mirror modes */
  3703. +enum mmal_parameter_mirror {
  3704. + MMAL_PARAM_MIRROR_NONE,
  3705. + MMAL_PARAM_MIRROR_VERTICAL,
  3706. + MMAL_PARAM_MIRROR_HORIZONTAL,
  3707. + MMAL_PARAM_MIRROR_BOTH,
  3708. +};
  3709. +
  3710. +enum mmal_parameter_displaytransform {
  3711. + MMAL_DISPLAY_ROT0 = 0,
  3712. + MMAL_DISPLAY_MIRROR_ROT0 = 1,
  3713. + MMAL_DISPLAY_MIRROR_ROT180 = 2,
  3714. + MMAL_DISPLAY_ROT180 = 3,
  3715. + MMAL_DISPLAY_MIRROR_ROT90 = 4,
  3716. + MMAL_DISPLAY_ROT270 = 5,
  3717. + MMAL_DISPLAY_ROT90 = 6,
  3718. + MMAL_DISPLAY_MIRROR_ROT270 = 7,
  3719. +};
  3720. +
  3721. +enum mmal_parameter_displaymode {
  3722. + MMAL_DISPLAY_MODE_FILL = 0,
  3723. + MMAL_DISPLAY_MODE_LETTERBOX = 1,
  3724. +};
  3725. +
  3726. +enum mmal_parameter_displayset {
  3727. + MMAL_DISPLAY_SET_NONE = 0,
  3728. + MMAL_DISPLAY_SET_NUM = 1,
  3729. + MMAL_DISPLAY_SET_FULLSCREEN = 2,
  3730. + MMAL_DISPLAY_SET_TRANSFORM = 4,
  3731. + MMAL_DISPLAY_SET_DEST_RECT = 8,
  3732. + MMAL_DISPLAY_SET_SRC_RECT = 0x10,
  3733. + MMAL_DISPLAY_SET_MODE = 0x20,
  3734. + MMAL_DISPLAY_SET_PIXEL = 0x40,
  3735. + MMAL_DISPLAY_SET_NOASPECT = 0x80,
  3736. + MMAL_DISPLAY_SET_LAYER = 0x100,
  3737. + MMAL_DISPLAY_SET_COPYPROTECT = 0x200,
  3738. + MMAL_DISPLAY_SET_ALPHA = 0x400,
  3739. +};
  3740. +
  3741. +struct mmal_parameter_displayregion {
  3742. + /** Bitfield that indicates which fields are set and should be
  3743. + * used. All other fields will maintain their current value.
  3744. + * \ref MMAL_DISPLAYSET_T defines the bits that can be
  3745. + * combined.
  3746. + */
  3747. + u32 set;
  3748. +
  3749. + /** Describes the display output device, with 0 typically
  3750. + * being a directly connected LCD display. The actual values
  3751. + * will depend on the hardware. Code using hard-wired numbers
  3752. + * (e.g. 2) is certain to fail.
  3753. + */
  3754. +
  3755. + u32 display_num;
  3756. + /** Indicates that we are using the full device screen area,
  3757. + * rather than a window of the display. If zero, then
  3758. + * dest_rect is used to specify a region of the display to
  3759. + * use.
  3760. + */
  3761. +
  3762. + s32 fullscreen;
  3763. + /** Indicates any rotation or flipping used to map frames onto
  3764. + * the natural display orientation.
  3765. + */
  3766. + u32 transform; /* enum mmal_parameter_displaytransform */
  3767. +
  3768. + /** Where to display the frame within the screen, if
  3769. + * fullscreen is zero.
  3770. + */
  3771. + struct vchiq_mmal_rect dest_rect;
  3772. +
  3773. + /** Indicates which area of the frame to display. If all
  3774. + * values are zero, the whole frame will be used.
  3775. + */
  3776. + struct vchiq_mmal_rect src_rect;
  3777. +
  3778. + /** If set to non-zero, indicates that any display scaling
  3779. + * should disregard the aspect ratio of the frame region being
  3780. + * displayed.
  3781. + */
  3782. + s32 noaspect;
  3783. +
  3784. + /** Indicates how the image should be scaled to fit the
  3785. + * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates
  3786. + * that the image should fill the screen by potentially
  3787. + * cropping the frames. Setting \code mode \endcode to \code
  3788. + * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the
  3789. + * source region should be displayed and black bars added if
  3790. + * necessary.
  3791. + */
  3792. + u32 mode; /* enum mmal_parameter_displaymode */
  3793. +
  3794. + /** If non-zero, defines the width of a source pixel relative
  3795. + * to \code pixel_y \endcode. If zero, then pixels default to
  3796. + * being square.
  3797. + */
  3798. + u32 pixel_x;
  3799. +
  3800. + /** If non-zero, defines the height of a source pixel relative
  3801. + * to \code pixel_x \endcode. If zero, then pixels default to
  3802. + * being square.
  3803. + */
  3804. + u32 pixel_y;
  3805. +
  3806. + /** Sets the relative depth of the images, with greater values
  3807. + * being in front of smaller values.
  3808. + */
  3809. + u32 layer;
  3810. +
  3811. + /** Set to non-zero to ensure copy protection is used on
  3812. + * output.
  3813. + */
  3814. + s32 copyprotect_required;
  3815. +
  3816. + /** Level of opacity of the layer, where zero is fully
  3817. + * transparent and 255 is fully opaque.
  3818. + */
  3819. + u32 alpha;
  3820. +};
  3821. +
  3822. +#define MMAL_MAX_IMAGEFX_PARAMETERS 5
  3823. +
  3824. +struct mmal_parameter_imagefx_parameters {
  3825. + enum mmal_parameter_imagefx effect;
  3826. + u32 num_effect_params;
  3827. + u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS];
  3828. +};
  3829. --- /dev/null
  3830. +++ b/drivers/media/platform/bcm2835/mmal-vchiq.c
  3831. @@ -0,0 +1,1916 @@
  3832. +/*
  3833. + * Broadcom BM2835 V4L2 driver
  3834. + *
  3835. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  3836. + *
  3837. + * This file is subject to the terms and conditions of the GNU General Public
  3838. + * License. See the file COPYING in the main directory of this archive
  3839. + * for more details.
  3840. + *
  3841. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  3842. + * Dave Stevenson <dsteve@broadcom.com>
  3843. + * Simon Mellor <simellor@broadcom.com>
  3844. + * Luke Diamand <luked@broadcom.com>
  3845. + *
  3846. + * V4L2 driver MMAL vchiq interface code
  3847. + */
  3848. +
  3849. +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  3850. +
  3851. +#include <linux/errno.h>
  3852. +#include <linux/kernel.h>
  3853. +#include <linux/mutex.h>
  3854. +#include <linux/mm.h>
  3855. +#include <linux/slab.h>
  3856. +#include <linux/completion.h>
  3857. +#include <linux/vmalloc.h>
  3858. +#include <asm/cacheflush.h>
  3859. +#include <media/videobuf2-vmalloc.h>
  3860. +
  3861. +#include "mmal-common.h"
  3862. +#include "mmal-vchiq.h"
  3863. +#include "mmal-msg.h"
  3864. +
  3865. +#define USE_VCHIQ_ARM
  3866. +#include "interface/vchi/vchi.h"
  3867. +
  3868. +/* maximum number of components supported */
  3869. +#define VCHIQ_MMAL_MAX_COMPONENTS 4
  3870. +
  3871. +/*#define FULL_MSG_DUMP 1*/
  3872. +
  3873. +#ifdef DEBUG
  3874. +static const char *const msg_type_names[] = {
  3875. + "UNKNOWN",
  3876. + "QUIT",
  3877. + "SERVICE_CLOSED",
  3878. + "GET_VERSION",
  3879. + "COMPONENT_CREATE",
  3880. + "COMPONENT_DESTROY",
  3881. + "COMPONENT_ENABLE",
  3882. + "COMPONENT_DISABLE",
  3883. + "PORT_INFO_GET",
  3884. + "PORT_INFO_SET",
  3885. + "PORT_ACTION",
  3886. + "BUFFER_FROM_HOST",
  3887. + "BUFFER_TO_HOST",
  3888. + "GET_STATS",
  3889. + "PORT_PARAMETER_SET",
  3890. + "PORT_PARAMETER_GET",
  3891. + "EVENT_TO_HOST",
  3892. + "GET_CORE_STATS_FOR_PORT",
  3893. + "OPAQUE_ALLOCATOR",
  3894. + "CONSUME_MEM",
  3895. + "LMK",
  3896. + "OPAQUE_ALLOCATOR_DESC",
  3897. + "DRM_GET_LHS32",
  3898. + "DRM_GET_TIME",
  3899. + "BUFFER_FROM_HOST_ZEROLEN",
  3900. + "PORT_FLUSH",
  3901. + "HOST_LOG",
  3902. +};
  3903. +#endif
  3904. +
  3905. +static const char *const port_action_type_names[] = {
  3906. + "UNKNOWN",
  3907. + "ENABLE",
  3908. + "DISABLE",
  3909. + "FLUSH",
  3910. + "CONNECT",
  3911. + "DISCONNECT",
  3912. + "SET_REQUIREMENTS",
  3913. +};
  3914. +
  3915. +#if defined(DEBUG)
  3916. +#if defined(FULL_MSG_DUMP)
  3917. +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
  3918. + do { \
  3919. + pr_debug(TITLE" type:%s(%d) length:%d\n", \
  3920. + msg_type_names[(MSG)->h.type], \
  3921. + (MSG)->h.type, (MSG_LEN)); \
  3922. + print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \
  3923. + 16, 4, (MSG), \
  3924. + sizeof(struct mmal_msg_header), 1); \
  3925. + print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \
  3926. + 16, 4, \
  3927. + ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\
  3928. + (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \
  3929. + } while (0)
  3930. +#else
  3931. +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \
  3932. + { \
  3933. + pr_debug(TITLE" type:%s(%d) length:%d\n", \
  3934. + msg_type_names[(MSG)->h.type], \
  3935. + (MSG)->h.type, (MSG_LEN)); \
  3936. + }
  3937. +#endif
  3938. +#else
  3939. +#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE)
  3940. +#endif
  3941. +
  3942. +/* normal message context */
  3943. +struct mmal_msg_context {
  3944. + union {
  3945. + struct {
  3946. + /* work struct for defered callback - must come first */
  3947. + struct work_struct work;
  3948. + /* mmal instance */
  3949. + struct vchiq_mmal_instance *instance;
  3950. + /* mmal port */
  3951. + struct vchiq_mmal_port *port;
  3952. + /* actual buffer used to store bulk reply */
  3953. + struct mmal_buffer *buffer;
  3954. + /* amount of buffer used */
  3955. + unsigned long buffer_used;
  3956. + /* MMAL buffer flags */
  3957. + u32 mmal_flags;
  3958. + /* Presentation and Decode timestamps */
  3959. + s64 pts;
  3960. + s64 dts;
  3961. +
  3962. + int status; /* context status */
  3963. +
  3964. + } bulk; /* bulk data */
  3965. +
  3966. + struct {
  3967. + /* message handle to release */
  3968. + VCHI_HELD_MSG_T msg_handle;
  3969. + /* pointer to received message */
  3970. + struct mmal_msg *msg;
  3971. + /* received message length */
  3972. + u32 msg_len;
  3973. + /* completion upon reply */
  3974. + struct completion cmplt;
  3975. + } sync; /* synchronous response */
  3976. + } u;
  3977. +
  3978. +};
  3979. +
  3980. +struct vchiq_mmal_instance {
  3981. + VCHI_SERVICE_HANDLE_T handle;
  3982. +
  3983. + /* ensure serialised access to service */
  3984. + struct mutex vchiq_mutex;
  3985. +
  3986. + /* ensure serialised access to bulk operations */
  3987. + struct mutex bulk_mutex;
  3988. +
  3989. + /* vmalloc page to receive scratch bulk xfers into */
  3990. + void *bulk_scratch;
  3991. +
  3992. + /* component to use next */
  3993. + int component_idx;
  3994. + struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS];
  3995. +};
  3996. +
  3997. +static struct mmal_msg_context *get_msg_context(struct vchiq_mmal_instance
  3998. + *instance)
  3999. +{
  4000. + struct mmal_msg_context *msg_context;
  4001. +
  4002. + /* todo: should this be allocated from a pool to avoid kmalloc */
  4003. + msg_context = kmalloc(sizeof(*msg_context), GFP_KERNEL);
  4004. + memset(msg_context, 0, sizeof(*msg_context));
  4005. +
  4006. + return msg_context;
  4007. +}
  4008. +
  4009. +static void release_msg_context(struct mmal_msg_context *msg_context)
  4010. +{
  4011. + kfree(msg_context);
  4012. +}
  4013. +
  4014. +/* deals with receipt of event to host message */
  4015. +static void event_to_host_cb(struct vchiq_mmal_instance *instance,
  4016. + struct mmal_msg *msg, u32 msg_len)
  4017. +{
  4018. + pr_debug("unhandled event\n");
  4019. + pr_debug("component:%p port type:%d num:%d cmd:0x%x length:%d\n",
  4020. + msg->u.event_to_host.client_component,
  4021. + msg->u.event_to_host.port_type,
  4022. + msg->u.event_to_host.port_num,
  4023. + msg->u.event_to_host.cmd, msg->u.event_to_host.length);
  4024. +}
  4025. +
  4026. +/* workqueue scheduled callback
  4027. + *
  4028. + * we do this because it is important we do not call any other vchiq
  4029. + * sync calls from witin the message delivery thread
  4030. + */
  4031. +static void buffer_work_cb(struct work_struct *work)
  4032. +{
  4033. + struct mmal_msg_context *msg_context = (struct mmal_msg_context *)work;
  4034. +
  4035. + msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance,
  4036. + msg_context->u.bulk.port,
  4037. + msg_context->u.bulk.status,
  4038. + msg_context->u.bulk.buffer,
  4039. + msg_context->u.bulk.buffer_used,
  4040. + msg_context->u.bulk.mmal_flags,
  4041. + msg_context->u.bulk.dts,
  4042. + msg_context->u.bulk.pts);
  4043. +
  4044. + /* release message context */
  4045. + release_msg_context(msg_context);
  4046. +}
  4047. +
  4048. +/* enqueue a bulk receive for a given message context */
  4049. +static int bulk_receive(struct vchiq_mmal_instance *instance,
  4050. + struct mmal_msg *msg,
  4051. + struct mmal_msg_context *msg_context)
  4052. +{
  4053. + unsigned long rd_len;
  4054. + unsigned long flags = 0;
  4055. + int ret;
  4056. +
  4057. + /* bulk mutex stops other bulk operations while we have a
  4058. + * receive in progress - released in callback
  4059. + */
  4060. + ret = mutex_lock_interruptible(&instance->bulk_mutex);
  4061. + if (ret != 0)
  4062. + return ret;
  4063. +
  4064. + rd_len = msg->u.buffer_from_host.buffer_header.length;
  4065. +
  4066. + /* take buffer from queue */
  4067. + spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags);
  4068. + if (list_empty(&msg_context->u.bulk.port->buffers)) {
  4069. + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
  4070. + pr_err("buffer list empty trying to submit bulk receive\n");
  4071. +
  4072. + /* todo: this is a serious error, we should never have
  4073. + * commited a buffer_to_host operation to the mmal
  4074. + * port without the buffer to back it up (underflow
  4075. + * handling) and there is no obvious way to deal with
  4076. + * this - how is the mmal servie going to react when
  4077. + * we fail to do the xfer and reschedule a buffer when
  4078. + * it arrives? perhaps a starved flag to indicate a
  4079. + * waiting bulk receive?
  4080. + */
  4081. +
  4082. + mutex_unlock(&instance->bulk_mutex);
  4083. +
  4084. + return -EINVAL;
  4085. + }
  4086. +
  4087. + msg_context->u.bulk.buffer =
  4088. + list_entry(msg_context->u.bulk.port->buffers.next,
  4089. + struct mmal_buffer, list);
  4090. + list_del(&msg_context->u.bulk.buffer->list);
  4091. +
  4092. + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
  4093. +
  4094. + /* ensure we do not overrun the available buffer */
  4095. + if (rd_len > msg_context->u.bulk.buffer->buffer_size) {
  4096. + rd_len = msg_context->u.bulk.buffer->buffer_size;
  4097. + pr_warn("short read as not enough receive buffer space\n");
  4098. + /* todo: is this the correct response, what happens to
  4099. + * the rest of the message data?
  4100. + */
  4101. + }
  4102. +
  4103. + /* store length */
  4104. + msg_context->u.bulk.buffer_used = rd_len;
  4105. + msg_context->u.bulk.mmal_flags =
  4106. + msg->u.buffer_from_host.buffer_header.flags;
  4107. + msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts;
  4108. + msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts;
  4109. +
  4110. + // only need to flush L1 cache here, as VCHIQ takes care of the L2
  4111. + // cache.
  4112. + __cpuc_flush_dcache_area(msg_context->u.bulk.buffer->buffer, rd_len);
  4113. +
  4114. + /* queue the bulk submission */
  4115. + vchi_service_use(instance->handle);
  4116. + ret = vchi_bulk_queue_receive(instance->handle,
  4117. + msg_context->u.bulk.buffer->buffer,
  4118. + /* Actual receive needs to be a multiple
  4119. + * of 4 bytes
  4120. + */
  4121. + (rd_len + 3) & ~3,
  4122. + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
  4123. + VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
  4124. + msg_context);
  4125. +
  4126. + vchi_service_release(instance->handle);
  4127. +
  4128. + if (ret != 0) {
  4129. + /* callback will not be clearing the mutex */
  4130. + mutex_unlock(&instance->bulk_mutex);
  4131. + }
  4132. +
  4133. + return ret;
  4134. +}
  4135. +
  4136. +/* enque a dummy bulk receive for a given message context */
  4137. +static int dummy_bulk_receive(struct vchiq_mmal_instance *instance,
  4138. + struct mmal_msg_context *msg_context)
  4139. +{
  4140. + int ret;
  4141. +
  4142. + /* bulk mutex stops other bulk operations while we have a
  4143. + * receive in progress - released in callback
  4144. + */
  4145. + ret = mutex_lock_interruptible(&instance->bulk_mutex);
  4146. + if (ret != 0)
  4147. + return ret;
  4148. +
  4149. + /* zero length indicates this was a dummy transfer */
  4150. + msg_context->u.bulk.buffer_used = 0;
  4151. +
  4152. + /* queue the bulk submission */
  4153. + vchi_service_use(instance->handle);
  4154. +
  4155. + ret = vchi_bulk_queue_receive(instance->handle,
  4156. + instance->bulk_scratch,
  4157. + 8,
  4158. + VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE |
  4159. + VCHI_FLAGS_BLOCK_UNTIL_QUEUED,
  4160. + msg_context);
  4161. +
  4162. + vchi_service_release(instance->handle);
  4163. +
  4164. + if (ret != 0) {
  4165. + /* callback will not be clearing the mutex */
  4166. + mutex_unlock(&instance->bulk_mutex);
  4167. + }
  4168. +
  4169. + return ret;
  4170. +}
  4171. +
  4172. +/* data in message, memcpy from packet into output buffer */
  4173. +static int inline_receive(struct vchiq_mmal_instance *instance,
  4174. + struct mmal_msg *msg,
  4175. + struct mmal_msg_context *msg_context)
  4176. +{
  4177. + unsigned long flags = 0;
  4178. +
  4179. + /* take buffer from queue */
  4180. + spin_lock_irqsave(&msg_context->u.bulk.port->slock, flags);
  4181. + if (list_empty(&msg_context->u.bulk.port->buffers)) {
  4182. + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
  4183. + pr_err("buffer list empty trying to receive inline\n");
  4184. +
  4185. + /* todo: this is a serious error, we should never have
  4186. + * commited a buffer_to_host operation to the mmal
  4187. + * port without the buffer to back it up (with
  4188. + * underflow handling) and there is no obvious way to
  4189. + * deal with this. Less bad than the bulk case as we
  4190. + * can just drop this on the floor but...unhelpful
  4191. + */
  4192. + return -EINVAL;
  4193. + }
  4194. +
  4195. + msg_context->u.bulk.buffer =
  4196. + list_entry(msg_context->u.bulk.port->buffers.next,
  4197. + struct mmal_buffer, list);
  4198. + list_del(&msg_context->u.bulk.buffer->list);
  4199. +
  4200. + spin_unlock_irqrestore(&msg_context->u.bulk.port->slock, flags);
  4201. +
  4202. + memcpy(msg_context->u.bulk.buffer->buffer,
  4203. + msg->u.buffer_from_host.short_data,
  4204. + msg->u.buffer_from_host.payload_in_message);
  4205. +
  4206. + msg_context->u.bulk.buffer_used =
  4207. + msg->u.buffer_from_host.payload_in_message;
  4208. +
  4209. + return 0;
  4210. +}
  4211. +
  4212. +/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */
  4213. +static int
  4214. +buffer_from_host(struct vchiq_mmal_instance *instance,
  4215. + struct vchiq_mmal_port *port, struct mmal_buffer *buf)
  4216. +{
  4217. + struct mmal_msg_context *msg_context;
  4218. + struct mmal_msg m;
  4219. + int ret;
  4220. +
  4221. + pr_debug("instance:%p buffer:%p\n", instance->handle, buf);
  4222. +
  4223. + /* bulk mutex stops other bulk operations while we
  4224. + * have a receive in progress
  4225. + */
  4226. + if (mutex_lock_interruptible(&instance->bulk_mutex))
  4227. + return -EINTR;
  4228. +
  4229. + /* get context */
  4230. + msg_context = get_msg_context(instance);
  4231. + if (msg_context == NULL)
  4232. + return -ENOMEM;
  4233. +
  4234. + /* store bulk message context for when data arrives */
  4235. + msg_context->u.bulk.instance = instance;
  4236. + msg_context->u.bulk.port = port;
  4237. + msg_context->u.bulk.buffer = NULL; /* not valid until bulk xfer */
  4238. + msg_context->u.bulk.buffer_used = 0;
  4239. +
  4240. + /* initialise work structure ready to schedule callback */
  4241. + INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb);
  4242. +
  4243. + /* prep the buffer from host message */
  4244. + memset(&m, 0xbc, sizeof(m)); /* just to make debug clearer */
  4245. +
  4246. + m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST;
  4247. + m.h.magic = MMAL_MAGIC;
  4248. + m.h.context = msg_context;
  4249. + m.h.status = 0;
  4250. +
  4251. + /* drvbuf is our private data passed back */
  4252. + m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC;
  4253. + m.u.buffer_from_host.drvbuf.component_handle = port->component->handle;
  4254. + m.u.buffer_from_host.drvbuf.port_handle = port->handle;
  4255. + m.u.buffer_from_host.drvbuf.client_context = msg_context;
  4256. +
  4257. + /* buffer header */
  4258. + m.u.buffer_from_host.buffer_header.cmd = 0;
  4259. + m.u.buffer_from_host.buffer_header.data = buf->buffer;
  4260. + m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
  4261. + m.u.buffer_from_host.buffer_header.length = 0; /* nothing used yet */
  4262. + m.u.buffer_from_host.buffer_header.offset = 0; /* no offset */
  4263. + m.u.buffer_from_host.buffer_header.flags = 0; /* no flags */
  4264. + m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN;
  4265. + m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN;
  4266. +
  4267. + /* clear buffer type sepecific data */
  4268. + memset(&m.u.buffer_from_host.buffer_header_type_specific, 0,
  4269. + sizeof(m.u.buffer_from_host.buffer_header_type_specific));
  4270. +
  4271. + /* no payload in message */
  4272. + m.u.buffer_from_host.payload_in_message = 0;
  4273. +
  4274. + vchi_service_use(instance->handle);
  4275. +
  4276. + ret = vchi_msg_queue(instance->handle, &m,
  4277. + sizeof(struct mmal_msg_header) +
  4278. + sizeof(m.u.buffer_from_host),
  4279. + VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  4280. +
  4281. + if (ret != 0) {
  4282. + release_msg_context(msg_context);
  4283. + /* todo: is this correct error value? */
  4284. + }
  4285. +
  4286. + vchi_service_release(instance->handle);
  4287. +
  4288. + mutex_unlock(&instance->bulk_mutex);
  4289. +
  4290. + return ret;
  4291. +}
  4292. +
  4293. +/* submit a buffer to the mmal sevice
  4294. + *
  4295. + * the buffer_from_host uses size data from the ports next available
  4296. + * mmal_buffer and deals with there being no buffer available by
  4297. + * incrementing the underflow for later
  4298. + */
  4299. +static int port_buffer_from_host(struct vchiq_mmal_instance *instance,
  4300. + struct vchiq_mmal_port *port)
  4301. +{
  4302. + int ret;
  4303. + struct mmal_buffer *buf;
  4304. + unsigned long flags = 0;
  4305. +
  4306. + if (!port->enabled)
  4307. + return -EINVAL;
  4308. +
  4309. + /* peek buffer from queue */
  4310. + spin_lock_irqsave(&port->slock, flags);
  4311. + if (list_empty(&port->buffers)) {
  4312. + port->buffer_underflow++;
  4313. + spin_unlock_irqrestore(&port->slock, flags);
  4314. + return -ENOSPC;
  4315. + }
  4316. +
  4317. + buf = list_entry(port->buffers.next, struct mmal_buffer, list);
  4318. +
  4319. + spin_unlock_irqrestore(&port->slock, flags);
  4320. +
  4321. + /* issue buffer to mmal service */
  4322. + ret = buffer_from_host(instance, port, buf);
  4323. + if (ret) {
  4324. + pr_err("adding buffer header failed\n");
  4325. + /* todo: how should this be dealt with */
  4326. + }
  4327. +
  4328. + return ret;
  4329. +}
  4330. +
  4331. +/* deals with receipt of buffer to host message */
  4332. +static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
  4333. + struct mmal_msg *msg, u32 msg_len)
  4334. +{
  4335. + struct mmal_msg_context *msg_context;
  4336. +
  4337. + pr_debug("buffer_to_host_cb: instance:%p msg:%p msg_len:%d\n",
  4338. + instance, msg, msg_len);
  4339. +
  4340. + if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) {
  4341. + msg_context = msg->u.buffer_from_host.drvbuf.client_context;
  4342. + } else {
  4343. + pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n");
  4344. + return;
  4345. + }
  4346. +
  4347. + if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) {
  4348. + /* message reception had an error */
  4349. + pr_warn("error %d in reply\n", msg->h.status);
  4350. +
  4351. + msg_context->u.bulk.status = msg->h.status;
  4352. +
  4353. + } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
  4354. + /* empty buffer */
  4355. + if (msg->u.buffer_from_host.buffer_header.flags &
  4356. + MMAL_BUFFER_HEADER_FLAG_EOS) {
  4357. + msg_context->u.bulk.status =
  4358. + dummy_bulk_receive(instance, msg_context);
  4359. + if (msg_context->u.bulk.status == 0)
  4360. + return; /* successful bulk submission, bulk
  4361. + * completion will trigger callback
  4362. + */
  4363. + } else {
  4364. + /* do callback with empty buffer - not EOS though */
  4365. + msg_context->u.bulk.status = 0;
  4366. + msg_context->u.bulk.buffer_used = 0;
  4367. + }
  4368. + } else if (msg->u.buffer_from_host.payload_in_message == 0) {
  4369. + /* data is not in message, queue a bulk receive */
  4370. + msg_context->u.bulk.status =
  4371. + bulk_receive(instance, msg, msg_context);
  4372. + if (msg_context->u.bulk.status == 0)
  4373. + return; /* successful bulk submission, bulk
  4374. + * completion will trigger callback
  4375. + */
  4376. +
  4377. + /* failed to submit buffer, this will end badly */
  4378. + pr_err("error %d on bulk submission\n",
  4379. + msg_context->u.bulk.status);
  4380. +
  4381. + } else if (msg->u.buffer_from_host.payload_in_message <=
  4382. + MMAL_VC_SHORT_DATA) {
  4383. + /* data payload within message */
  4384. + msg_context->u.bulk.status = inline_receive(instance, msg,
  4385. + msg_context);
  4386. + } else {
  4387. + pr_err("message with invalid short payload\n");
  4388. +
  4389. + /* signal error */
  4390. + msg_context->u.bulk.status = -EINVAL;
  4391. + msg_context->u.bulk.buffer_used =
  4392. + msg->u.buffer_from_host.payload_in_message;
  4393. + }
  4394. +
  4395. + /* replace the buffer header */
  4396. + port_buffer_from_host(instance, msg_context->u.bulk.port);
  4397. +
  4398. + /* schedule the port callback */
  4399. + schedule_work(&msg_context->u.bulk.work);
  4400. +}
  4401. +
  4402. +static void bulk_receive_cb(struct vchiq_mmal_instance *instance,
  4403. + struct mmal_msg_context *msg_context)
  4404. +{
  4405. + /* bulk receive operation complete */
  4406. + mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex);
  4407. +
  4408. + /* replace the buffer header */
  4409. + port_buffer_from_host(msg_context->u.bulk.instance,
  4410. + msg_context->u.bulk.port);
  4411. +
  4412. + msg_context->u.bulk.status = 0;
  4413. +
  4414. + /* schedule the port callback */
  4415. + schedule_work(&msg_context->u.bulk.work);
  4416. +}
  4417. +
  4418. +static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
  4419. + struct mmal_msg_context *msg_context)
  4420. +{
  4421. + pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context);
  4422. +
  4423. + /* bulk receive operation complete */
  4424. + mutex_unlock(&msg_context->u.bulk.instance->bulk_mutex);
  4425. +
  4426. + /* replace the buffer header */
  4427. + port_buffer_from_host(msg_context->u.bulk.instance,
  4428. + msg_context->u.bulk.port);
  4429. +
  4430. + msg_context->u.bulk.status = -EINTR;
  4431. +
  4432. + schedule_work(&msg_context->u.bulk.work);
  4433. +}
  4434. +
  4435. +/* incoming event service callback */
  4436. +static void service_callback(void *param,
  4437. + const VCHI_CALLBACK_REASON_T reason,
  4438. + void *bulk_ctx)
  4439. +{
  4440. + struct vchiq_mmal_instance *instance = param;
  4441. + int status;
  4442. + u32 msg_len;
  4443. + struct mmal_msg *msg;
  4444. + VCHI_HELD_MSG_T msg_handle;
  4445. +
  4446. + if (!instance) {
  4447. + pr_err("Message callback passed NULL instance\n");
  4448. + return;
  4449. + }
  4450. +
  4451. + switch (reason) {
  4452. + case VCHI_CALLBACK_MSG_AVAILABLE:
  4453. + status = vchi_msg_hold(instance->handle, (void **)&msg,
  4454. + &msg_len, VCHI_FLAGS_NONE, &msg_handle);
  4455. + if (status) {
  4456. + pr_err("Unable to dequeue a message (%d)\n", status);
  4457. + break;
  4458. + }
  4459. +
  4460. + DBG_DUMP_MSG(msg, msg_len, "<<< reply message");
  4461. +
  4462. + /* handling is different for buffer messages */
  4463. + switch (msg->h.type) {
  4464. +
  4465. + case MMAL_MSG_TYPE_BUFFER_FROM_HOST:
  4466. + vchi_held_msg_release(&msg_handle);
  4467. + break;
  4468. +
  4469. + case MMAL_MSG_TYPE_EVENT_TO_HOST:
  4470. + event_to_host_cb(instance, msg, msg_len);
  4471. + vchi_held_msg_release(&msg_handle);
  4472. +
  4473. + break;
  4474. +
  4475. + case MMAL_MSG_TYPE_BUFFER_TO_HOST:
  4476. + buffer_to_host_cb(instance, msg, msg_len);
  4477. + vchi_held_msg_release(&msg_handle);
  4478. + break;
  4479. +
  4480. + default:
  4481. + /* messages dependant on header context to complete */
  4482. +
  4483. + /* todo: the msg.context really ought to be sanity
  4484. + * checked before we just use it, afaict it comes back
  4485. + * and is used raw from the videocore. Perhaps it
  4486. + * should be verified the address lies in the kernel
  4487. + * address space.
  4488. + */
  4489. + if (msg->h.context == NULL) {
  4490. + pr_err("received message context was null!\n");
  4491. + vchi_held_msg_release(&msg_handle);
  4492. + break;
  4493. + }
  4494. +
  4495. + /* fill in context values */
  4496. + msg->h.context->u.sync.msg_handle = msg_handle;
  4497. + msg->h.context->u.sync.msg = msg;
  4498. + msg->h.context->u.sync.msg_len = msg_len;
  4499. +
  4500. + /* todo: should this check (completion_done()
  4501. + * == 1) for no one waiting? or do we need a
  4502. + * flag to tell us the completion has been
  4503. + * interrupted so we can free the message and
  4504. + * its context. This probably also solves the
  4505. + * message arriving after interruption todo
  4506. + * below
  4507. + */
  4508. +
  4509. + /* complete message so caller knows it happened */
  4510. + complete(&msg->h.context->u.sync.cmplt);
  4511. + break;
  4512. + }
  4513. +
  4514. + break;
  4515. +
  4516. + case VCHI_CALLBACK_BULK_RECEIVED:
  4517. + bulk_receive_cb(instance, bulk_ctx);
  4518. + break;
  4519. +
  4520. + case VCHI_CALLBACK_BULK_RECEIVE_ABORTED:
  4521. + bulk_abort_cb(instance, bulk_ctx);
  4522. + break;
  4523. +
  4524. + case VCHI_CALLBACK_SERVICE_CLOSED:
  4525. + /* TODO: consider if this requires action if received when
  4526. + * driver is not explicitly closing the service
  4527. + */
  4528. + break;
  4529. +
  4530. + default:
  4531. + pr_err("Received unhandled message reason %d\n", reason);
  4532. + break;
  4533. + }
  4534. +}
  4535. +
  4536. +static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance,
  4537. + struct mmal_msg *msg,
  4538. + unsigned int payload_len,
  4539. + struct mmal_msg **msg_out,
  4540. + VCHI_HELD_MSG_T *msg_handle_out)
  4541. +{
  4542. + struct mmal_msg_context msg_context;
  4543. + int ret;
  4544. +
  4545. + /* payload size must not cause message to exceed max size */
  4546. + if (payload_len >
  4547. + (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) {
  4548. + pr_err("payload length %d exceeds max:%d\n", payload_len,
  4549. + (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header)));
  4550. + return -EINVAL;
  4551. + }
  4552. +
  4553. + init_completion(&msg_context.u.sync.cmplt);
  4554. +
  4555. + msg->h.magic = MMAL_MAGIC;
  4556. + msg->h.context = &msg_context;
  4557. + msg->h.status = 0;
  4558. +
  4559. + DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len),
  4560. + ">>> sync message");
  4561. +
  4562. + vchi_service_use(instance->handle);
  4563. +
  4564. + ret = vchi_msg_queue(instance->handle,
  4565. + msg,
  4566. + sizeof(struct mmal_msg_header) + payload_len,
  4567. + VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL);
  4568. +
  4569. + vchi_service_release(instance->handle);
  4570. +
  4571. + if (ret) {
  4572. + pr_err("error %d queuing message\n", ret);
  4573. + return ret;
  4574. + }
  4575. +
  4576. + ret = wait_for_completion_timeout(&msg_context.u.sync.cmplt, HZ);
  4577. + if (ret <= 0) {
  4578. + pr_err("error %d waiting for sync completion\n", ret);
  4579. + if (ret == 0)
  4580. + ret = -ETIME;
  4581. + /* todo: what happens if the message arrives after aborting */
  4582. + return ret;
  4583. + }
  4584. +
  4585. + *msg_out = msg_context.u.sync.msg;
  4586. + *msg_handle_out = msg_context.u.sync.msg_handle;
  4587. +
  4588. + return 0;
  4589. +}
  4590. +
  4591. +static void dump_port_info(struct vchiq_mmal_port *port)
  4592. +{
  4593. + pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled);
  4594. +
  4595. + pr_debug("buffer minimum num:%d size:%d align:%d\n",
  4596. + port->minimum_buffer.num,
  4597. + port->minimum_buffer.size, port->minimum_buffer.alignment);
  4598. +
  4599. + pr_debug("buffer recommended num:%d size:%d align:%d\n",
  4600. + port->recommended_buffer.num,
  4601. + port->recommended_buffer.size,
  4602. + port->recommended_buffer.alignment);
  4603. +
  4604. + pr_debug("buffer current values num:%d size:%d align:%d\n",
  4605. + port->current_buffer.num,
  4606. + port->current_buffer.size, port->current_buffer.alignment);
  4607. +
  4608. + pr_debug("elementry stream: type:%d encoding:0x%x varient:0x%x\n",
  4609. + port->format.type,
  4610. + port->format.encoding, port->format.encoding_variant);
  4611. +
  4612. + pr_debug(" bitrate:%d flags:0x%x\n",
  4613. + port->format.bitrate, port->format.flags);
  4614. +
  4615. + if (port->format.type == MMAL_ES_TYPE_VIDEO) {
  4616. + pr_debug
  4617. + ("es video format: width:%d height:%d colourspace:0x%x\n",
  4618. + port->es.video.width, port->es.video.height,
  4619. + port->es.video.color_space);
  4620. +
  4621. + pr_debug(" : crop xywh %d,%d,%d,%d\n",
  4622. + port->es.video.crop.x,
  4623. + port->es.video.crop.y,
  4624. + port->es.video.crop.width, port->es.video.crop.height);
  4625. + pr_debug(" : framerate %d/%d aspect %d/%d\n",
  4626. + port->es.video.frame_rate.num,
  4627. + port->es.video.frame_rate.den,
  4628. + port->es.video.par.num, port->es.video.par.den);
  4629. + }
  4630. +}
  4631. +
  4632. +static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p)
  4633. +{
  4634. +
  4635. + /* todo do readonly fields need setting at all? */
  4636. + p->type = port->type;
  4637. + p->index = port->index;
  4638. + p->index_all = 0;
  4639. + p->is_enabled = port->enabled;
  4640. + p->buffer_num_min = port->minimum_buffer.num;
  4641. + p->buffer_size_min = port->minimum_buffer.size;
  4642. + p->buffer_alignment_min = port->minimum_buffer.alignment;
  4643. + p->buffer_num_recommended = port->recommended_buffer.num;
  4644. + p->buffer_size_recommended = port->recommended_buffer.size;
  4645. +
  4646. + /* only three writable fields in a port */
  4647. + p->buffer_num = port->current_buffer.num;
  4648. + p->buffer_size = port->current_buffer.size;
  4649. + p->userdata = port;
  4650. +}
  4651. +
  4652. +static int port_info_set(struct vchiq_mmal_instance *instance,
  4653. + struct vchiq_mmal_port *port)
  4654. +{
  4655. + int ret;
  4656. + struct mmal_msg m;
  4657. + struct mmal_msg *rmsg;
  4658. + VCHI_HELD_MSG_T rmsg_handle;
  4659. +
  4660. + pr_debug("setting port info port %p\n", port);
  4661. + if (!port)
  4662. + return -1;
  4663. + dump_port_info(port);
  4664. +
  4665. + m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET;
  4666. +
  4667. + m.u.port_info_set.component_handle = port->component->handle;
  4668. + m.u.port_info_set.port_type = port->type;
  4669. + m.u.port_info_set.port_index = port->index;
  4670. +
  4671. + port_to_mmal_msg(port, &m.u.port_info_set.port);
  4672. +
  4673. + /* elementry stream format setup */
  4674. + m.u.port_info_set.format.type = port->format.type;
  4675. + m.u.port_info_set.format.encoding = port->format.encoding;
  4676. + m.u.port_info_set.format.encoding_variant =
  4677. + port->format.encoding_variant;
  4678. + m.u.port_info_set.format.bitrate = port->format.bitrate;
  4679. + m.u.port_info_set.format.flags = port->format.flags;
  4680. +
  4681. + memcpy(&m.u.port_info_set.es, &port->es,
  4682. + sizeof(union mmal_es_specific_format));
  4683. +
  4684. + m.u.port_info_set.format.extradata_size = port->format.extradata_size;
  4685. + memcpy(rmsg->u.port_info_set.extradata, port->format.extradata,
  4686. + port->format.extradata_size);
  4687. +
  4688. + ret = send_synchronous_mmal_msg(instance, &m,
  4689. + sizeof(m.u.port_info_set),
  4690. + &rmsg, &rmsg_handle);
  4691. + if (ret)
  4692. + return ret;
  4693. +
  4694. + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) {
  4695. + /* got an unexpected message type in reply */
  4696. + ret = -EINVAL;
  4697. + goto release_msg;
  4698. + }
  4699. +
  4700. + /* return operation status */
  4701. + ret = -rmsg->u.port_info_get_reply.status;
  4702. +
  4703. + pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret,
  4704. + port->component->handle, port->handle);
  4705. +
  4706. +release_msg:
  4707. + vchi_held_msg_release(&rmsg_handle);
  4708. +
  4709. + return ret;
  4710. +
  4711. +}
  4712. +
  4713. +/* use port info get message to retrive port information */
  4714. +static int port_info_get(struct vchiq_mmal_instance *instance,
  4715. + struct vchiq_mmal_port *port)
  4716. +{
  4717. + int ret;
  4718. + struct mmal_msg m;
  4719. + struct mmal_msg *rmsg;
  4720. + VCHI_HELD_MSG_T rmsg_handle;
  4721. +
  4722. + /* port info time */
  4723. + m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET;
  4724. + m.u.port_info_get.component_handle = port->component->handle;
  4725. + m.u.port_info_get.port_type = port->type;
  4726. + m.u.port_info_get.index = port->index;
  4727. +
  4728. + ret = send_synchronous_mmal_msg(instance, &m,
  4729. + sizeof(m.u.port_info_get),
  4730. + &rmsg, &rmsg_handle);
  4731. + if (ret)
  4732. + return ret;
  4733. +
  4734. + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) {
  4735. + /* got an unexpected message type in reply */
  4736. + ret = -EINVAL;
  4737. + goto release_msg;
  4738. + }
  4739. +
  4740. + /* return operation status */
  4741. + ret = -rmsg->u.port_info_get_reply.status;
  4742. + if (ret != MMAL_MSG_STATUS_SUCCESS)
  4743. + goto release_msg;
  4744. +
  4745. + if (rmsg->u.port_info_get_reply.port.is_enabled == 0)
  4746. + port->enabled = false;
  4747. + else
  4748. + port->enabled = true;
  4749. +
  4750. + /* copy the values out of the message */
  4751. + port->handle = rmsg->u.port_info_get_reply.port_handle;
  4752. +
  4753. + /* port type and index cached to use on port info set becuase
  4754. + * it does not use a port handle
  4755. + */
  4756. + port->type = rmsg->u.port_info_get_reply.port_type;
  4757. + port->index = rmsg->u.port_info_get_reply.port_index;
  4758. +
  4759. + port->minimum_buffer.num =
  4760. + rmsg->u.port_info_get_reply.port.buffer_num_min;
  4761. + port->minimum_buffer.size =
  4762. + rmsg->u.port_info_get_reply.port.buffer_size_min;
  4763. + port->minimum_buffer.alignment =
  4764. + rmsg->u.port_info_get_reply.port.buffer_alignment_min;
  4765. +
  4766. + port->recommended_buffer.alignment =
  4767. + rmsg->u.port_info_get_reply.port.buffer_alignment_min;
  4768. + port->recommended_buffer.num =
  4769. + rmsg->u.port_info_get_reply.port.buffer_num_recommended;
  4770. +
  4771. + port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num;
  4772. + port->current_buffer.size =
  4773. + rmsg->u.port_info_get_reply.port.buffer_size;
  4774. +
  4775. + /* stream format */
  4776. + port->format.type = rmsg->u.port_info_get_reply.format.type;
  4777. + port->format.encoding = rmsg->u.port_info_get_reply.format.encoding;
  4778. + port->format.encoding_variant =
  4779. + rmsg->u.port_info_get_reply.format.encoding_variant;
  4780. + port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate;
  4781. + port->format.flags = rmsg->u.port_info_get_reply.format.flags;
  4782. +
  4783. + /* elementry stream format */
  4784. + memcpy(&port->es,
  4785. + &rmsg->u.port_info_get_reply.es,
  4786. + sizeof(union mmal_es_specific_format));
  4787. + port->format.es = &port->es;
  4788. +
  4789. + port->format.extradata_size =
  4790. + rmsg->u.port_info_get_reply.format.extradata_size;
  4791. + memcpy(port->format.extradata,
  4792. + rmsg->u.port_info_get_reply.extradata,
  4793. + port->format.extradata_size);
  4794. +
  4795. + pr_debug("received port info\n");
  4796. + dump_port_info(port);
  4797. +
  4798. +release_msg:
  4799. +
  4800. + pr_debug("%s:result:%d component:0x%x port:%d\n",
  4801. + __func__, ret, port->component->handle, port->handle);
  4802. +
  4803. + vchi_held_msg_release(&rmsg_handle);
  4804. +
  4805. + return ret;
  4806. +}
  4807. +
  4808. +/* create comonent on vc */
  4809. +static int create_component(struct vchiq_mmal_instance *instance,
  4810. + struct vchiq_mmal_component *component,
  4811. + const char *name)
  4812. +{
  4813. + int ret;
  4814. + struct mmal_msg m;
  4815. + struct mmal_msg *rmsg;
  4816. + VCHI_HELD_MSG_T rmsg_handle;
  4817. +
  4818. + /* build component create message */
  4819. + m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
  4820. + m.u.component_create.client_component = component;
  4821. + strncpy(m.u.component_create.name, name,
  4822. + sizeof(m.u.component_create.name));
  4823. +
  4824. + ret = send_synchronous_mmal_msg(instance, &m,
  4825. + sizeof(m.u.component_create),
  4826. + &rmsg, &rmsg_handle);
  4827. + if (ret)
  4828. + return ret;
  4829. +
  4830. + if (rmsg->h.type != m.h.type) {
  4831. + /* got an unexpected message type in reply */
  4832. + ret = -EINVAL;
  4833. + goto release_msg;
  4834. + }
  4835. +
  4836. + ret = -rmsg->u.component_create_reply.status;
  4837. + if (ret != MMAL_MSG_STATUS_SUCCESS)
  4838. + goto release_msg;
  4839. +
  4840. + /* a valid component response received */
  4841. + component->handle = rmsg->u.component_create_reply.component_handle;
  4842. + component->inputs = rmsg->u.component_create_reply.input_num;
  4843. + component->outputs = rmsg->u.component_create_reply.output_num;
  4844. + component->clocks = rmsg->u.component_create_reply.clock_num;
  4845. +
  4846. + pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n",
  4847. + component->handle,
  4848. + component->inputs, component->outputs, component->clocks);
  4849. +
  4850. +release_msg:
  4851. + vchi_held_msg_release(&rmsg_handle);
  4852. +
  4853. + return ret;
  4854. +}
  4855. +
  4856. +/* destroys a component on vc */
  4857. +static int destroy_component(struct vchiq_mmal_instance *instance,
  4858. + struct vchiq_mmal_component *component)
  4859. +{
  4860. + int ret;
  4861. + struct mmal_msg m;
  4862. + struct mmal_msg *rmsg;
  4863. + VCHI_HELD_MSG_T rmsg_handle;
  4864. +
  4865. + m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY;
  4866. + m.u.component_destroy.component_handle = component->handle;
  4867. +
  4868. + ret = send_synchronous_mmal_msg(instance, &m,
  4869. + sizeof(m.u.component_destroy),
  4870. + &rmsg, &rmsg_handle);
  4871. + if (ret)
  4872. + return ret;
  4873. +
  4874. + if (rmsg->h.type != m.h.type) {
  4875. + /* got an unexpected message type in reply */
  4876. + ret = -EINVAL;
  4877. + goto release_msg;
  4878. + }
  4879. +
  4880. + ret = -rmsg->u.component_destroy_reply.status;
  4881. +
  4882. +release_msg:
  4883. +
  4884. + vchi_held_msg_release(&rmsg_handle);
  4885. +
  4886. + return ret;
  4887. +}
  4888. +
  4889. +/* enable a component on vc */
  4890. +static int enable_component(struct vchiq_mmal_instance *instance,
  4891. + struct vchiq_mmal_component *component)
  4892. +{
  4893. + int ret;
  4894. + struct mmal_msg m;
  4895. + struct mmal_msg *rmsg;
  4896. + VCHI_HELD_MSG_T rmsg_handle;
  4897. +
  4898. + m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE;
  4899. + m.u.component_enable.component_handle = component->handle;
  4900. +
  4901. + ret = send_synchronous_mmal_msg(instance, &m,
  4902. + sizeof(m.u.component_enable),
  4903. + &rmsg, &rmsg_handle);
  4904. + if (ret)
  4905. + return ret;
  4906. +
  4907. + if (rmsg->h.type != m.h.type) {
  4908. + /* got an unexpected message type in reply */
  4909. + ret = -EINVAL;
  4910. + goto release_msg;
  4911. + }
  4912. +
  4913. + ret = -rmsg->u.component_enable_reply.status;
  4914. +
  4915. +release_msg:
  4916. + vchi_held_msg_release(&rmsg_handle);
  4917. +
  4918. + return ret;
  4919. +}
  4920. +
  4921. +/* disable a component on vc */
  4922. +static int disable_component(struct vchiq_mmal_instance *instance,
  4923. + struct vchiq_mmal_component *component)
  4924. +{
  4925. + int ret;
  4926. + struct mmal_msg m;
  4927. + struct mmal_msg *rmsg;
  4928. + VCHI_HELD_MSG_T rmsg_handle;
  4929. +
  4930. + m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE;
  4931. + m.u.component_disable.component_handle = component->handle;
  4932. +
  4933. + ret = send_synchronous_mmal_msg(instance, &m,
  4934. + sizeof(m.u.component_disable),
  4935. + &rmsg, &rmsg_handle);
  4936. + if (ret)
  4937. + return ret;
  4938. +
  4939. + if (rmsg->h.type != m.h.type) {
  4940. + /* got an unexpected message type in reply */
  4941. + ret = -EINVAL;
  4942. + goto release_msg;
  4943. + }
  4944. +
  4945. + ret = -rmsg->u.component_disable_reply.status;
  4946. +
  4947. +release_msg:
  4948. +
  4949. + vchi_held_msg_release(&rmsg_handle);
  4950. +
  4951. + return ret;
  4952. +}
  4953. +
  4954. +/* get version of mmal implementation */
  4955. +static int get_version(struct vchiq_mmal_instance *instance,
  4956. + u32 *major_out, u32 *minor_out)
  4957. +{
  4958. + int ret;
  4959. + struct mmal_msg m;
  4960. + struct mmal_msg *rmsg;
  4961. + VCHI_HELD_MSG_T rmsg_handle;
  4962. +
  4963. + m.h.type = MMAL_MSG_TYPE_GET_VERSION;
  4964. +
  4965. + ret = send_synchronous_mmal_msg(instance, &m,
  4966. + sizeof(m.u.version),
  4967. + &rmsg, &rmsg_handle);
  4968. + if (ret)
  4969. + return ret;
  4970. +
  4971. + if (rmsg->h.type != m.h.type) {
  4972. + /* got an unexpected message type in reply */
  4973. + ret = -EINVAL;
  4974. + goto release_msg;
  4975. + }
  4976. +
  4977. + *major_out = rmsg->u.version.major;
  4978. + *minor_out = rmsg->u.version.minor;
  4979. +
  4980. +release_msg:
  4981. + vchi_held_msg_release(&rmsg_handle);
  4982. +
  4983. + return ret;
  4984. +}
  4985. +
  4986. +/* do a port action with a port as a parameter */
  4987. +static int port_action_port(struct vchiq_mmal_instance *instance,
  4988. + struct vchiq_mmal_port *port,
  4989. + enum mmal_msg_port_action_type action_type)
  4990. +{
  4991. + int ret;
  4992. + struct mmal_msg m;
  4993. + struct mmal_msg *rmsg;
  4994. + VCHI_HELD_MSG_T rmsg_handle;
  4995. +
  4996. + m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
  4997. + m.u.port_action_port.component_handle = port->component->handle;
  4998. + m.u.port_action_port.port_handle = port->handle;
  4999. + m.u.port_action_port.action = action_type;
  5000. +
  5001. + port_to_mmal_msg(port, &m.u.port_action_port.port);
  5002. +
  5003. + ret = send_synchronous_mmal_msg(instance, &m,
  5004. + sizeof(m.u.port_action_port),
  5005. + &rmsg, &rmsg_handle);
  5006. + if (ret)
  5007. + return ret;
  5008. +
  5009. + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
  5010. + /* got an unexpected message type in reply */
  5011. + ret = -EINVAL;
  5012. + goto release_msg;
  5013. + }
  5014. +
  5015. + ret = -rmsg->u.port_action_reply.status;
  5016. +
  5017. + pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n",
  5018. + __func__,
  5019. + ret, port->component->handle, port->handle,
  5020. + port_action_type_names[action_type], action_type);
  5021. +
  5022. +release_msg:
  5023. + vchi_held_msg_release(&rmsg_handle);
  5024. +
  5025. + return ret;
  5026. +}
  5027. +
  5028. +/* do a port action with handles as parameters */
  5029. +static int port_action_handle(struct vchiq_mmal_instance *instance,
  5030. + struct vchiq_mmal_port *port,
  5031. + enum mmal_msg_port_action_type action_type,
  5032. + u32 connect_component_handle,
  5033. + u32 connect_port_handle)
  5034. +{
  5035. + int ret;
  5036. + struct mmal_msg m;
  5037. + struct mmal_msg *rmsg;
  5038. + VCHI_HELD_MSG_T rmsg_handle;
  5039. +
  5040. + m.h.type = MMAL_MSG_TYPE_PORT_ACTION;
  5041. +
  5042. + m.u.port_action_handle.component_handle = port->component->handle;
  5043. + m.u.port_action_handle.port_handle = port->handle;
  5044. + m.u.port_action_handle.action = action_type;
  5045. +
  5046. + m.u.port_action_handle.connect_component_handle =
  5047. + connect_component_handle;
  5048. + m.u.port_action_handle.connect_port_handle = connect_port_handle;
  5049. +
  5050. + ret = send_synchronous_mmal_msg(instance, &m,
  5051. + sizeof(m.u.port_action_handle),
  5052. + &rmsg, &rmsg_handle);
  5053. + if (ret)
  5054. + return ret;
  5055. +
  5056. + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) {
  5057. + /* got an unexpected message type in reply */
  5058. + ret = -EINVAL;
  5059. + goto release_msg;
  5060. + }
  5061. +
  5062. + ret = -rmsg->u.port_action_reply.status;
  5063. +
  5064. + pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)" \
  5065. + " connect component:0x%x connect port:%d\n",
  5066. + __func__,
  5067. + ret, port->component->handle, port->handle,
  5068. + port_action_type_names[action_type],
  5069. + action_type, connect_component_handle, connect_port_handle);
  5070. +
  5071. +release_msg:
  5072. + vchi_held_msg_release(&rmsg_handle);
  5073. +
  5074. + return ret;
  5075. +}
  5076. +
  5077. +static int port_parameter_set(struct vchiq_mmal_instance *instance,
  5078. + struct vchiq_mmal_port *port,
  5079. + u32 parameter_id, void *value, u32 value_size)
  5080. +{
  5081. + int ret;
  5082. + struct mmal_msg m;
  5083. + struct mmal_msg *rmsg;
  5084. + VCHI_HELD_MSG_T rmsg_handle;
  5085. +
  5086. + m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET;
  5087. +
  5088. + m.u.port_parameter_set.component_handle = port->component->handle;
  5089. + m.u.port_parameter_set.port_handle = port->handle;
  5090. + m.u.port_parameter_set.id = parameter_id;
  5091. + m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size;
  5092. + memcpy(&m.u.port_parameter_set.value, value, value_size);
  5093. +
  5094. + ret = send_synchronous_mmal_msg(instance, &m,
  5095. + (4 * sizeof(u32)) + value_size,
  5096. + &rmsg, &rmsg_handle);
  5097. + if (ret)
  5098. + return ret;
  5099. +
  5100. + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) {
  5101. + /* got an unexpected message type in reply */
  5102. + ret = -EINVAL;
  5103. + goto release_msg;
  5104. + }
  5105. +
  5106. + ret = -rmsg->u.port_parameter_set_reply.status;
  5107. +
  5108. + pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n",
  5109. + __func__,
  5110. + ret, port->component->handle, port->handle, parameter_id);
  5111. +
  5112. +release_msg:
  5113. + vchi_held_msg_release(&rmsg_handle);
  5114. +
  5115. + return ret;
  5116. +}
  5117. +
  5118. +static int port_parameter_get(struct vchiq_mmal_instance *instance,
  5119. + struct vchiq_mmal_port *port,
  5120. + u32 parameter_id, void *value, u32 *value_size)
  5121. +{
  5122. + int ret;
  5123. + struct mmal_msg m;
  5124. + struct mmal_msg *rmsg;
  5125. + VCHI_HELD_MSG_T rmsg_handle;
  5126. +
  5127. + m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET;
  5128. +
  5129. + m.u.port_parameter_get.component_handle = port->component->handle;
  5130. + m.u.port_parameter_get.port_handle = port->handle;
  5131. + m.u.port_parameter_get.id = parameter_id;
  5132. + m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size;
  5133. +
  5134. + ret = send_synchronous_mmal_msg(instance, &m,
  5135. + sizeof(struct
  5136. + mmal_msg_port_parameter_get),
  5137. + &rmsg, &rmsg_handle);
  5138. + if (ret)
  5139. + return ret;
  5140. +
  5141. + if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) {
  5142. + /* got an unexpected message type in reply */
  5143. + pr_err("Incorrect reply type %d\n", rmsg->h.type);
  5144. + ret = -EINVAL;
  5145. + goto release_msg;
  5146. + }
  5147. +
  5148. + ret = -rmsg->u.port_parameter_get_reply.status;
  5149. + if (ret) {
  5150. + /* Copy only as much as we have space for
  5151. + * but report true size of parameter
  5152. + */
  5153. + memcpy(value, &rmsg->u.port_parameter_get_reply.value,
  5154. + *value_size);
  5155. + *value_size = rmsg->u.port_parameter_get_reply.size;
  5156. + } else
  5157. + memcpy(value, &rmsg->u.port_parameter_get_reply.value,
  5158. + rmsg->u.port_parameter_get_reply.size);
  5159. +
  5160. + pr_info("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__,
  5161. + ret, port->component->handle, port->handle, parameter_id);
  5162. +
  5163. +release_msg:
  5164. + vchi_held_msg_release(&rmsg_handle);
  5165. +
  5166. + return ret;
  5167. +}
  5168. +
  5169. +/* disables a port and drains buffers from it */
  5170. +static int port_disable(struct vchiq_mmal_instance *instance,
  5171. + struct vchiq_mmal_port *port)
  5172. +{
  5173. + int ret;
  5174. + struct list_head *q, *buf_head;
  5175. + unsigned long flags = 0;
  5176. +
  5177. + if (!port->enabled)
  5178. + return 0;
  5179. +
  5180. + port->enabled = false;
  5181. +
  5182. + ret = port_action_port(instance, port,
  5183. + MMAL_MSG_PORT_ACTION_TYPE_DISABLE);
  5184. + if (ret == 0) {
  5185. +
  5186. + /* drain all queued buffers on port */
  5187. + spin_lock_irqsave(&port->slock, flags);
  5188. +
  5189. + list_for_each_safe(buf_head, q, &port->buffers) {
  5190. + struct mmal_buffer *mmalbuf;
  5191. + mmalbuf = list_entry(buf_head, struct mmal_buffer,
  5192. + list);
  5193. + list_del(buf_head);
  5194. + if (port->buffer_cb)
  5195. + port->buffer_cb(instance,
  5196. + port, 0, mmalbuf, 0, 0,
  5197. + MMAL_TIME_UNKNOWN,
  5198. + MMAL_TIME_UNKNOWN);
  5199. + }
  5200. +
  5201. + spin_unlock_irqrestore(&port->slock, flags);
  5202. +
  5203. + ret = port_info_get(instance, port);
  5204. + }
  5205. +
  5206. + return ret;
  5207. +}
  5208. +
  5209. +/* enable a port */
  5210. +static int port_enable(struct vchiq_mmal_instance *instance,
  5211. + struct vchiq_mmal_port *port)
  5212. +{
  5213. + unsigned int hdr_count;
  5214. + struct list_head *buf_head;
  5215. + int ret;
  5216. +
  5217. + if (port->enabled)
  5218. + return 0;
  5219. +
  5220. + /* ensure there are enough buffers queued to cover the buffer headers */
  5221. + if (port->buffer_cb != NULL) {
  5222. + hdr_count = 0;
  5223. + list_for_each(buf_head, &port->buffers) {
  5224. + hdr_count++;
  5225. + }
  5226. + if (hdr_count < port->current_buffer.num)
  5227. + return -ENOSPC;
  5228. + }
  5229. +
  5230. + ret = port_action_port(instance, port,
  5231. + MMAL_MSG_PORT_ACTION_TYPE_ENABLE);
  5232. + if (ret)
  5233. + goto done;
  5234. +
  5235. + port->enabled = true;
  5236. +
  5237. + if (port->buffer_cb) {
  5238. + /* send buffer headers to videocore */
  5239. + hdr_count = 1;
  5240. + list_for_each(buf_head, &port->buffers) {
  5241. + struct mmal_buffer *mmalbuf;
  5242. + mmalbuf = list_entry(buf_head, struct mmal_buffer,
  5243. + list);
  5244. + ret = buffer_from_host(instance, port, mmalbuf);
  5245. + if (ret)
  5246. + goto done;
  5247. +
  5248. + hdr_count++;
  5249. + if (hdr_count > port->current_buffer.num)
  5250. + break;
  5251. + }
  5252. + }
  5253. +
  5254. + ret = port_info_get(instance, port);
  5255. +
  5256. +done:
  5257. + return ret;
  5258. +}
  5259. +
  5260. +/* ------------------------------------------------------------------
  5261. + * Exported API
  5262. + *------------------------------------------------------------------*/
  5263. +
  5264. +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
  5265. + struct vchiq_mmal_port *port)
  5266. +{
  5267. + int ret;
  5268. +
  5269. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5270. + return -EINTR;
  5271. +
  5272. + ret = port_info_set(instance, port);
  5273. + if (ret)
  5274. + goto release_unlock;
  5275. +
  5276. + /* read what has actually been set */
  5277. + ret = port_info_get(instance, port);
  5278. +
  5279. +release_unlock:
  5280. + mutex_unlock(&instance->vchiq_mutex);
  5281. +
  5282. + return ret;
  5283. +
  5284. +}
  5285. +
  5286. +int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
  5287. + struct vchiq_mmal_port *port,
  5288. + u32 parameter, void *value, u32 value_size)
  5289. +{
  5290. + int ret;
  5291. +
  5292. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5293. + return -EINTR;
  5294. +
  5295. + ret = port_parameter_set(instance, port, parameter, value, value_size);
  5296. +
  5297. + mutex_unlock(&instance->vchiq_mutex);
  5298. +
  5299. + return ret;
  5300. +}
  5301. +
  5302. +int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
  5303. + struct vchiq_mmal_port *port,
  5304. + u32 parameter, void *value, u32 *value_size)
  5305. +{
  5306. + int ret;
  5307. +
  5308. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5309. + return -EINTR;
  5310. +
  5311. + ret = port_parameter_get(instance, port, parameter, value, value_size);
  5312. +
  5313. + mutex_unlock(&instance->vchiq_mutex);
  5314. +
  5315. + return ret;
  5316. +}
  5317. +
  5318. +/* enable a port
  5319. + *
  5320. + * enables a port and queues buffers for satisfying callbacks if we
  5321. + * provide a callback handler
  5322. + */
  5323. +int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance,
  5324. + struct vchiq_mmal_port *port,
  5325. + vchiq_mmal_buffer_cb buffer_cb)
  5326. +{
  5327. + int ret;
  5328. +
  5329. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5330. + return -EINTR;
  5331. +
  5332. + /* already enabled - noop */
  5333. + if (port->enabled) {
  5334. + ret = 0;
  5335. + goto unlock;
  5336. + }
  5337. +
  5338. + port->buffer_cb = buffer_cb;
  5339. +
  5340. + ret = port_enable(instance, port);
  5341. +
  5342. +unlock:
  5343. + mutex_unlock(&instance->vchiq_mutex);
  5344. +
  5345. + return ret;
  5346. +}
  5347. +
  5348. +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
  5349. + struct vchiq_mmal_port *port)
  5350. +{
  5351. + int ret;
  5352. +
  5353. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5354. + return -EINTR;
  5355. +
  5356. + if (!port->enabled) {
  5357. + mutex_unlock(&instance->vchiq_mutex);
  5358. + return 0;
  5359. + }
  5360. +
  5361. + ret = port_disable(instance, port);
  5362. +
  5363. + mutex_unlock(&instance->vchiq_mutex);
  5364. +
  5365. + return ret;
  5366. +}
  5367. +
  5368. +/* ports will be connected in a tunneled manner so data buffers
  5369. + * are not handled by client.
  5370. + */
  5371. +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
  5372. + struct vchiq_mmal_port *src,
  5373. + struct vchiq_mmal_port *dst)
  5374. +{
  5375. + int ret;
  5376. +
  5377. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5378. + return -EINTR;
  5379. +
  5380. + /* disconnect ports if connected */
  5381. + if (src->connected != NULL) {
  5382. + ret = port_disable(instance, src);
  5383. + if (ret) {
  5384. + pr_err("failed disabling src port(%d)\n", ret);
  5385. + goto release_unlock;
  5386. + }
  5387. +
  5388. + /* do not need to disable the destination port as they
  5389. + * are connected and it is done automatically
  5390. + */
  5391. +
  5392. + ret = port_action_handle(instance, src,
  5393. + MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT,
  5394. + src->connected->component->handle,
  5395. + src->connected->handle);
  5396. + if (ret < 0) {
  5397. + pr_err("failed disconnecting src port\n");
  5398. + goto release_unlock;
  5399. + }
  5400. + src->connected->enabled = false;
  5401. + src->connected = NULL;
  5402. + }
  5403. +
  5404. + if (dst == NULL) {
  5405. + /* do not make new connection */
  5406. + ret = 0;
  5407. + pr_debug("not making new connection\n");
  5408. + goto release_unlock;
  5409. + }
  5410. +
  5411. + /* copy src port format to dst */
  5412. + dst->format.encoding = src->format.encoding;
  5413. + dst->es.video.width = src->es.video.width;
  5414. + dst->es.video.height = src->es.video.height;
  5415. + dst->es.video.crop.x = src->es.video.crop.x;
  5416. + dst->es.video.crop.y = src->es.video.crop.y;
  5417. + dst->es.video.crop.width = src->es.video.crop.width;
  5418. + dst->es.video.crop.height = src->es.video.crop.height;
  5419. + dst->es.video.frame_rate.num = src->es.video.frame_rate.num;
  5420. + dst->es.video.frame_rate.den = src->es.video.frame_rate.den;
  5421. +
  5422. + /* set new format */
  5423. + ret = port_info_set(instance, dst);
  5424. + if (ret) {
  5425. + pr_debug("setting port info failed\n");
  5426. + goto release_unlock;
  5427. + }
  5428. +
  5429. + /* read what has actually been set */
  5430. + ret = port_info_get(instance, dst);
  5431. + if (ret) {
  5432. + pr_debug("read back port info failed\n");
  5433. + goto release_unlock;
  5434. + }
  5435. +
  5436. + /* connect two ports together */
  5437. + ret = port_action_handle(instance, src,
  5438. + MMAL_MSG_PORT_ACTION_TYPE_CONNECT,
  5439. + dst->component->handle, dst->handle);
  5440. + if (ret < 0) {
  5441. + pr_debug("connecting port %d:%d to %d:%d failed\n",
  5442. + src->component->handle, src->handle,
  5443. + dst->component->handle, dst->handle);
  5444. + goto release_unlock;
  5445. + }
  5446. + src->connected = dst;
  5447. +
  5448. +release_unlock:
  5449. +
  5450. + mutex_unlock(&instance->vchiq_mutex);
  5451. +
  5452. + return ret;
  5453. +}
  5454. +
  5455. +int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
  5456. + struct vchiq_mmal_port *port,
  5457. + struct mmal_buffer *buffer)
  5458. +{
  5459. + unsigned long flags = 0;
  5460. +
  5461. + spin_lock_irqsave(&port->slock, flags);
  5462. + list_add_tail(&buffer->list, &port->buffers);
  5463. + spin_unlock_irqrestore(&port->slock, flags);
  5464. +
  5465. + /* the port previously underflowed because it was missing a
  5466. + * mmal_buffer which has just been added, submit that buffer
  5467. + * to the mmal service.
  5468. + */
  5469. + if (port->buffer_underflow) {
  5470. + port_buffer_from_host(instance, port);
  5471. + port->buffer_underflow--;
  5472. + }
  5473. +
  5474. + return 0;
  5475. +}
  5476. +
  5477. +/* Initialise a mmal component and its ports
  5478. + *
  5479. + */
  5480. +int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance,
  5481. + const char *name,
  5482. + struct vchiq_mmal_component **component_out)
  5483. +{
  5484. + int ret;
  5485. + int idx; /* port index */
  5486. + struct vchiq_mmal_component *component;
  5487. +
  5488. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5489. + return -EINTR;
  5490. +
  5491. + if (instance->component_idx == VCHIQ_MMAL_MAX_COMPONENTS) {
  5492. + ret = -EINVAL; /* todo is this correct error? */
  5493. + goto unlock;
  5494. + }
  5495. +
  5496. + component = &instance->component[instance->component_idx];
  5497. +
  5498. + ret = create_component(instance, component, name);
  5499. + if (ret < 0)
  5500. + goto unlock;
  5501. +
  5502. + /* ports info needs gathering */
  5503. + component->control.type = MMAL_PORT_TYPE_CONTROL;
  5504. + component->control.index = 0;
  5505. + component->control.component = component;
  5506. + spin_lock_init(&component->control.slock);
  5507. + INIT_LIST_HEAD(&component->control.buffers);
  5508. + ret = port_info_get(instance, &component->control);
  5509. + if (ret < 0)
  5510. + goto release_component;
  5511. +
  5512. + for (idx = 0; idx < component->inputs; idx++) {
  5513. + component->input[idx].type = MMAL_PORT_TYPE_INPUT;
  5514. + component->input[idx].index = idx;
  5515. + component->input[idx].component = component;
  5516. + spin_lock_init(&component->input[idx].slock);
  5517. + INIT_LIST_HEAD(&component->input[idx].buffers);
  5518. + ret = port_info_get(instance, &component->input[idx]);
  5519. + if (ret < 0)
  5520. + goto release_component;
  5521. + }
  5522. +
  5523. + for (idx = 0; idx < component->outputs; idx++) {
  5524. + component->output[idx].type = MMAL_PORT_TYPE_OUTPUT;
  5525. + component->output[idx].index = idx;
  5526. + component->output[idx].component = component;
  5527. + spin_lock_init(&component->output[idx].slock);
  5528. + INIT_LIST_HEAD(&component->output[idx].buffers);
  5529. + ret = port_info_get(instance, &component->output[idx]);
  5530. + if (ret < 0)
  5531. + goto release_component;
  5532. + }
  5533. +
  5534. + for (idx = 0; idx < component->clocks; idx++) {
  5535. + component->clock[idx].type = MMAL_PORT_TYPE_CLOCK;
  5536. + component->clock[idx].index = idx;
  5537. + component->clock[idx].component = component;
  5538. + spin_lock_init(&component->clock[idx].slock);
  5539. + INIT_LIST_HEAD(&component->clock[idx].buffers);
  5540. + ret = port_info_get(instance, &component->clock[idx]);
  5541. + if (ret < 0)
  5542. + goto release_component;
  5543. + }
  5544. +
  5545. + instance->component_idx++;
  5546. +
  5547. + *component_out = component;
  5548. +
  5549. + mutex_unlock(&instance->vchiq_mutex);
  5550. +
  5551. + return 0;
  5552. +
  5553. +release_component:
  5554. + destroy_component(instance, component);
  5555. +unlock:
  5556. + mutex_unlock(&instance->vchiq_mutex);
  5557. +
  5558. + return ret;
  5559. +}
  5560. +
  5561. +/*
  5562. + * cause a mmal component to be destroyed
  5563. + */
  5564. +int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance,
  5565. + struct vchiq_mmal_component *component)
  5566. +{
  5567. + int ret;
  5568. +
  5569. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5570. + return -EINTR;
  5571. +
  5572. + if (component->enabled)
  5573. + ret = disable_component(instance, component);
  5574. +
  5575. + ret = destroy_component(instance, component);
  5576. +
  5577. + mutex_unlock(&instance->vchiq_mutex);
  5578. +
  5579. + return ret;
  5580. +}
  5581. +
  5582. +/*
  5583. + * cause a mmal component to be enabled
  5584. + */
  5585. +int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance,
  5586. + struct vchiq_mmal_component *component)
  5587. +{
  5588. + int ret;
  5589. +
  5590. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5591. + return -EINTR;
  5592. +
  5593. + if (component->enabled) {
  5594. + mutex_unlock(&instance->vchiq_mutex);
  5595. + return 0;
  5596. + }
  5597. +
  5598. + ret = enable_component(instance, component);
  5599. + if (ret == 0)
  5600. + component->enabled = true;
  5601. +
  5602. + mutex_unlock(&instance->vchiq_mutex);
  5603. +
  5604. + return ret;
  5605. +}
  5606. +
  5607. +/*
  5608. + * cause a mmal component to be enabled
  5609. + */
  5610. +int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance,
  5611. + struct vchiq_mmal_component *component)
  5612. +{
  5613. + int ret;
  5614. +
  5615. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5616. + return -EINTR;
  5617. +
  5618. + if (!component->enabled) {
  5619. + mutex_unlock(&instance->vchiq_mutex);
  5620. + return 0;
  5621. + }
  5622. +
  5623. + ret = disable_component(instance, component);
  5624. + if (ret == 0)
  5625. + component->enabled = false;
  5626. +
  5627. + mutex_unlock(&instance->vchiq_mutex);
  5628. +
  5629. + return ret;
  5630. +}
  5631. +
  5632. +int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
  5633. + u32 *major_out, u32 *minor_out)
  5634. +{
  5635. + int ret;
  5636. +
  5637. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5638. + return -EINTR;
  5639. +
  5640. + ret = get_version(instance, major_out, minor_out);
  5641. +
  5642. + mutex_unlock(&instance->vchiq_mutex);
  5643. +
  5644. + return ret;
  5645. +}
  5646. +
  5647. +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance)
  5648. +{
  5649. + int status = 0;
  5650. +
  5651. + if (instance == NULL)
  5652. + return -EINVAL;
  5653. +
  5654. + if (mutex_lock_interruptible(&instance->vchiq_mutex))
  5655. + return -EINTR;
  5656. +
  5657. + vchi_service_use(instance->handle);
  5658. +
  5659. + status = vchi_service_close(instance->handle);
  5660. + if (status != 0)
  5661. + pr_err("mmal-vchiq: VCHIQ close failed");
  5662. +
  5663. + mutex_unlock(&instance->vchiq_mutex);
  5664. +
  5665. + vfree(instance->bulk_scratch);
  5666. +
  5667. + kfree(instance);
  5668. +
  5669. + return status;
  5670. +}
  5671. +
  5672. +int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance)
  5673. +{
  5674. + int status;
  5675. + struct vchiq_mmal_instance *instance;
  5676. + static VCHI_CONNECTION_T *vchi_connection;
  5677. + static VCHI_INSTANCE_T vchi_instance;
  5678. + SERVICE_CREATION_T params = {
  5679. + VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER),
  5680. + VC_MMAL_SERVER_NAME,
  5681. + vchi_connection,
  5682. + 0, /* rx fifo size (unused) */
  5683. + 0, /* tx fifo size (unused) */
  5684. + service_callback,
  5685. + NULL, /* service callback parameter */
  5686. + 1, /* unaligned bulk receives */
  5687. + 1, /* unaligned bulk transmits */
  5688. + 0 /* want crc check on bulk transfers */
  5689. + };
  5690. +
  5691. + /* compile time checks to ensure structure size as they are
  5692. + * directly (de)serialised from memory.
  5693. + */
  5694. +
  5695. + /* ensure the header structure has packed to the correct size */
  5696. + BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24);
  5697. +
  5698. + /* ensure message structure does not exceed maximum length */
  5699. + BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE);
  5700. +
  5701. + /* mmal port struct is correct size */
  5702. + BUILD_BUG_ON(sizeof(struct mmal_port) != 64);
  5703. +
  5704. + /* create a vchi instance */
  5705. + status = vchi_initialise(&vchi_instance);
  5706. + if (status) {
  5707. + pr_err("Failed to initialise VCHI instance (status=%d)\n",
  5708. + status);
  5709. + return -EIO;
  5710. + }
  5711. +
  5712. + status = vchi_connect(NULL, 0, vchi_instance);
  5713. + if (status) {
  5714. + pr_err("Failed to connect VCHI instance (status=%d)\n", status);
  5715. + return -EIO;
  5716. + }
  5717. +
  5718. + instance = kmalloc(sizeof(*instance), GFP_KERNEL);
  5719. + memset(instance, 0, sizeof(*instance));
  5720. +
  5721. + mutex_init(&instance->vchiq_mutex);
  5722. + mutex_init(&instance->bulk_mutex);
  5723. +
  5724. + instance->bulk_scratch = vmalloc(PAGE_SIZE);
  5725. +
  5726. + params.callback_param = instance;
  5727. +
  5728. + status = vchi_service_open(vchi_instance, &params, &instance->handle);
  5729. + if (status) {
  5730. + pr_err("Failed to open VCHI service connection (status=%d)\n",
  5731. + status);
  5732. + goto err_close_services;
  5733. + }
  5734. +
  5735. + vchi_service_release(instance->handle);
  5736. +
  5737. + *out_instance = instance;
  5738. +
  5739. + return 0;
  5740. +
  5741. +err_close_services:
  5742. +
  5743. + vchi_service_close(instance->handle);
  5744. + vfree(instance->bulk_scratch);
  5745. + kfree(instance);
  5746. + return -ENODEV;
  5747. +}
  5748. --- /dev/null
  5749. +++ b/drivers/media/platform/bcm2835/mmal-vchiq.h
  5750. @@ -0,0 +1,178 @@
  5751. +/*
  5752. + * Broadcom BM2835 V4L2 driver
  5753. + *
  5754. + * Copyright © 2013 Raspberry Pi (Trading) Ltd.
  5755. + *
  5756. + * This file is subject to the terms and conditions of the GNU General Public
  5757. + * License. See the file COPYING in the main directory of this archive
  5758. + * for more details.
  5759. + *
  5760. + * Authors: Vincent Sanders <vincent.sanders@collabora.co.uk>
  5761. + * Dave Stevenson <dsteve@broadcom.com>
  5762. + * Simon Mellor <simellor@broadcom.com>
  5763. + * Luke Diamand <luked@broadcom.com>
  5764. + *
  5765. + * MMAL interface to VCHIQ message passing
  5766. + */
  5767. +
  5768. +#ifndef MMAL_VCHIQ_H
  5769. +#define MMAL_VCHIQ_H
  5770. +
  5771. +#include "mmal-msg-format.h"
  5772. +
  5773. +#define MAX_PORT_COUNT 4
  5774. +
  5775. +/* Maximum size of the format extradata. */
  5776. +#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128
  5777. +
  5778. +struct vchiq_mmal_instance;
  5779. +
  5780. +enum vchiq_mmal_es_type {
  5781. + MMAL_ES_TYPE_UNKNOWN, /**< Unknown elementary stream type */
  5782. + MMAL_ES_TYPE_CONTROL, /**< Elementary stream of control commands */
  5783. + MMAL_ES_TYPE_AUDIO, /**< Audio elementary stream */
  5784. + MMAL_ES_TYPE_VIDEO, /**< Video elementary stream */
  5785. + MMAL_ES_TYPE_SUBPICTURE /**< Sub-picture elementary stream */
  5786. +};
  5787. +
  5788. +/* rectangle, used lots so it gets its own struct */
  5789. +struct vchiq_mmal_rect {
  5790. + s32 x;
  5791. + s32 y;
  5792. + s32 width;
  5793. + s32 height;
  5794. +};
  5795. +
  5796. +struct vchiq_mmal_port_buffer {
  5797. + unsigned int num; /* number of buffers */
  5798. + u32 size; /* size of buffers */
  5799. + u32 alignment; /* alignment of buffers */
  5800. +};
  5801. +
  5802. +struct vchiq_mmal_port;
  5803. +
  5804. +typedef void (*vchiq_mmal_buffer_cb)(
  5805. + struct vchiq_mmal_instance *instance,
  5806. + struct vchiq_mmal_port *port,
  5807. + int status, struct mmal_buffer *buffer,
  5808. + unsigned long length, u32 mmal_flags, s64 dts, s64 pts);
  5809. +
  5810. +struct vchiq_mmal_port {
  5811. + bool enabled;
  5812. + u32 handle;
  5813. + u32 type; /* port type, cached to use on port info set */
  5814. + u32 index; /* port index, cached to use on port info set */
  5815. +
  5816. + /* component port belongs to, allows simple deref */
  5817. + struct vchiq_mmal_component *component;
  5818. +
  5819. + struct vchiq_mmal_port *connected; /* port conencted to */
  5820. +
  5821. + /* buffer info */
  5822. + struct vchiq_mmal_port_buffer minimum_buffer;
  5823. + struct vchiq_mmal_port_buffer recommended_buffer;
  5824. + struct vchiq_mmal_port_buffer current_buffer;
  5825. +
  5826. + /* stream format */
  5827. + struct mmal_es_format format;
  5828. + /* elementry stream format */
  5829. + union mmal_es_specific_format es;
  5830. +
  5831. + /* data buffers to fill */
  5832. + struct list_head buffers;
  5833. + /* lock to serialise adding and removing buffers from list */
  5834. + spinlock_t slock;
  5835. + /* count of how many buffer header refils have failed because
  5836. + * there was no buffer to satisfy them
  5837. + */
  5838. + int buffer_underflow;
  5839. + /* callback on buffer completion */
  5840. + vchiq_mmal_buffer_cb buffer_cb;
  5841. + /* callback context */
  5842. + void *cb_ctx;
  5843. +};
  5844. +
  5845. +struct vchiq_mmal_component {
  5846. + bool enabled;
  5847. + u32 handle; /* VideoCore handle for component */
  5848. + u32 inputs; /* Number of input ports */
  5849. + u32 outputs; /* Number of output ports */
  5850. + u32 clocks; /* Number of clock ports */
  5851. + struct vchiq_mmal_port control; /* control port */
  5852. + struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */
  5853. + struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */
  5854. + struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */
  5855. +};
  5856. +
  5857. +
  5858. +int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance);
  5859. +int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance);
  5860. +
  5861. +/* Initialise a mmal component and its ports
  5862. +*
  5863. +*/
  5864. +int vchiq_mmal_component_init(
  5865. + struct vchiq_mmal_instance *instance,
  5866. + const char *name,
  5867. + struct vchiq_mmal_component **component_out);
  5868. +
  5869. +int vchiq_mmal_component_finalise(
  5870. + struct vchiq_mmal_instance *instance,
  5871. + struct vchiq_mmal_component *component);
  5872. +
  5873. +int vchiq_mmal_component_enable(
  5874. + struct vchiq_mmal_instance *instance,
  5875. + struct vchiq_mmal_component *component);
  5876. +
  5877. +int vchiq_mmal_component_disable(
  5878. + struct vchiq_mmal_instance *instance,
  5879. + struct vchiq_mmal_component *component);
  5880. +
  5881. +
  5882. +
  5883. +/* enable a mmal port
  5884. + *
  5885. + * enables a port and if a buffer callback provided enque buffer
  5886. + * headers as apropriate for the port.
  5887. + */
  5888. +int vchiq_mmal_port_enable(
  5889. + struct vchiq_mmal_instance *instance,
  5890. + struct vchiq_mmal_port *port,
  5891. + vchiq_mmal_buffer_cb buffer_cb);
  5892. +
  5893. +/* disable a port
  5894. + *
  5895. + * disable a port will dequeue any pending buffers
  5896. + */
  5897. +int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance,
  5898. + struct vchiq_mmal_port *port);
  5899. +
  5900. +
  5901. +int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
  5902. + struct vchiq_mmal_port *port,
  5903. + u32 parameter,
  5904. + void *value,
  5905. + u32 value_size);
  5906. +
  5907. +int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance,
  5908. + struct vchiq_mmal_port *port,
  5909. + u32 parameter,
  5910. + void *value,
  5911. + u32 *value_size);
  5912. +
  5913. +int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance,
  5914. + struct vchiq_mmal_port *port);
  5915. +
  5916. +int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance,
  5917. + struct vchiq_mmal_port *src,
  5918. + struct vchiq_mmal_port *dst);
  5919. +
  5920. +int vchiq_mmal_version(struct vchiq_mmal_instance *instance,
  5921. + u32 *major_out,
  5922. + u32 *minor_out);
  5923. +
  5924. +int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
  5925. + struct vchiq_mmal_port *port,
  5926. + struct mmal_buffer *buf);
  5927. +
  5928. +#endif /* MMAL_VCHIQ_H */