radio-tavarua.c 145 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038
  1. /* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. /*
  14. * Qualcomm Tavarua FM core driver
  15. */
  16. /* driver definitions */
  17. #define DRIVER_AUTHOR "Qualcomm"
  18. #define DRIVER_NAME "radio-tavarua"
  19. #define DRIVER_CARD "Qualcomm FM Radio Transceiver"
  20. #define DRIVER_DESC "I2C radio driver for Qualcomm FM Radio Transceiver "
  21. #define DRIVER_VERSION "1.0.0"
  22. #include <linux/version.h>
  23. #include <linux/init.h> /* Initdata */
  24. #include <linux/delay.h> /* udelay */
  25. #include <linux/uaccess.h> /* copy to/from user */
  26. #include <linux/kfifo.h> /* lock free circular buffer */
  27. #include <linux/param.h>
  28. #include <linux/i2c.h>
  29. #include <linux/irq.h>
  30. #include <linux/interrupt.h>
  31. /* kernel includes */
  32. #include <linux/kernel.h>
  33. #include <linux/module.h>
  34. #include <linux/version.h>
  35. #include <linux/videodev2.h>
  36. #include <linux/mutex.h>
  37. #include <media/v4l2-common.h>
  38. #include <asm/unaligned.h>
  39. #include <media/v4l2-ioctl.h>
  40. #include <linux/unistd.h>
  41. #include <asm/atomic.h>
  42. #include <media/tavarua.h>
  43. #include <linux/mfd/marimba.h>
  44. #include <linux/platform_device.h>
  45. #include <linux/workqueue.h>
  46. #include <linux/slab.h>
  47. /*
  48. regional parameters for radio device
  49. */
  50. struct region_params_t {
  51. enum tavarua_region_t region;
  52. unsigned int band_high;
  53. unsigned int band_low;
  54. char emphasis;
  55. char rds_std;
  56. char spacing;
  57. };
  58. struct srch_params_t {
  59. unsigned short srch_pi;
  60. unsigned char srch_pty;
  61. unsigned int preset_num;
  62. int get_list;
  63. };
  64. /* Main radio device structure,
  65. acts as a shadow copy of the
  66. actual tavaura registers */
  67. struct tavarua_device {
  68. struct video_device *videodev;
  69. /* driver management */
  70. atomic_t users;
  71. /* top level driver data */
  72. struct marimba *marimba;
  73. struct device *dev;
  74. /* platform specific functionality */
  75. struct marimba_fm_platform_data *pdata;
  76. unsigned int chipID;
  77. /*RDS buffers + Radio event buffer*/
  78. struct kfifo data_buf[TAVARUA_BUF_MAX];
  79. /* search paramters */
  80. struct srch_params_t srch_params;
  81. /* keep track of pending xfrs */
  82. int pending_xfrs[TAVARUA_XFR_MAX];
  83. int xfr_bytes_left;
  84. int xfr_in_progress;
  85. /* Transmit data */
  86. enum tavarua_xfr_ctrl_t tx_mode;
  87. /* synchrnous xfr data */
  88. unsigned char sync_xfr_regs[XFR_REG_NUM];
  89. struct completion sync_xfr_start;
  90. struct completion shutdown_done;
  91. struct completion sync_req_done;
  92. int tune_req;
  93. /* internal register status */
  94. unsigned char registers[RADIO_REGISTERS];
  95. /* regional settings */
  96. struct region_params_t region_params;
  97. /* power mode */
  98. int lp_mode;
  99. int handle_irq;
  100. /* global lock */
  101. struct mutex lock;
  102. /* buffer locks*/
  103. spinlock_t buf_lock[TAVARUA_BUF_MAX];
  104. /* work queue */
  105. struct workqueue_struct *wqueue;
  106. struct delayed_work work;
  107. /* wait queue for blocking event read */
  108. wait_queue_head_t event_queue;
  109. /* wait queue for raw rds read */
  110. wait_queue_head_t read_queue;
  111. /* PTY for FM Tx */
  112. int pty;
  113. /* PI for FM TX */
  114. int pi;
  115. /*PS repeatcount for PS Tx */
  116. int ps_repeatcount;
  117. int enable_optimized_srch_alg;
  118. unsigned char spur_table_size;
  119. struct fm_spur_data spur_data;
  120. atomic_t validate_channel;
  121. unsigned char is_station_valid;
  122. };
  123. /**************************************************************************
  124. * Module Parameters
  125. **************************************************************************/
  126. /* Radio Nr */
  127. static int radio_nr = -1;
  128. module_param(radio_nr, int, 0);
  129. MODULE_PARM_DESC(radio_nr, "Radio Nr");
  130. static int wait_timeout = WAIT_TIMEOUT;
  131. /* Bahama's version*/
  132. static u8 bahama_version;
  133. /* RDS buffer blocks */
  134. static unsigned int rds_buf = 100;
  135. module_param(rds_buf, uint, 0);
  136. MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
  137. /* static variables */
  138. static struct tavarua_device *private_data;
  139. /* forward declerations */
  140. static int tavarua_disable_interrupts(struct tavarua_device *radio);
  141. static int tavarua_setup_interrupts(struct tavarua_device *radio,
  142. enum radio_state_t state);
  143. static int tavarua_start(struct tavarua_device *radio,
  144. enum radio_state_t state);
  145. static int tavarua_request_irq(struct tavarua_device *radio);
  146. static void start_pending_xfr(struct tavarua_device *radio);
  147. static int update_spur_table(struct tavarua_device *radio);
  148. static int xfr_rdwr_data(struct tavarua_device *radio, int op, int size,
  149. unsigned long offset, unsigned char *buf);
  150. static int compute_MPX_DCC(struct tavarua_device *radio, int *val);
  151. /* work function */
  152. static void read_int_stat(struct work_struct *work);
  153. static int is_bahama(void)
  154. {
  155. int id = 0;
  156. switch (id = adie_get_detected_connectivity_type()) {
  157. case BAHAMA_ID:
  158. FMDBG("It is Bahama\n");
  159. return 1;
  160. case MARIMBA_ID:
  161. FMDBG("It is Marimba\n");
  162. return 0;
  163. default:
  164. printk(KERN_ERR "%s: unexpected adie connectivity type: %d\n",
  165. __func__, id);
  166. return -ENODEV;
  167. }
  168. }
  169. static int set_fm_slave_id(struct tavarua_device *radio)
  170. {
  171. int bahama_present = is_bahama();
  172. if (bahama_present == -ENODEV)
  173. return -ENODEV;
  174. if (unlikely(radio == NULL)) {
  175. FMDERR("%s:radio is null", __func__);
  176. return -EINVAL;
  177. }
  178. if (bahama_present)
  179. radio->marimba->mod_id = SLAVE_ID_BAHAMA_FM;
  180. else
  181. radio->marimba->mod_id = MARIMBA_SLAVE_ID_FM;
  182. return 0;
  183. }
  184. /*=============================================================================
  185. FUNCTION: tavarua_isr
  186. =============================================================================*/
  187. /**
  188. This function is called when GPIO is toggled. This functions queues the event
  189. to interrupt queue, which is later handled by isr handling funcion.
  190. i.e. INIT_DELAYED_WORK(&radio->work, read_int_stat);
  191. @param irq: irq that is toggled.
  192. @param dev_id: structure pointer passed by client.
  193. @return IRQ_HANDLED.
  194. */
  195. static irqreturn_t tavarua_isr(int irq, void *dev_id)
  196. {
  197. struct tavarua_device *radio = dev_id;
  198. /* schedule a tasklet to handle host intr */
  199. /* The call to queue_delayed_work ensures that a minimum delay (in jiffies)
  200. * passes before the work is actually executed. The return value from the
  201. * function is nonzero if the work_struct was actually added to queue
  202. * (otherwise, it may have already been there and will not be added a second
  203. * time).
  204. */
  205. if (unlikely(radio == NULL)) {
  206. FMDERR("%s:radio is null", __func__);
  207. return -EINVAL;
  208. }
  209. queue_delayed_work(radio->wqueue, &radio->work,
  210. msecs_to_jiffies(TAVARUA_DELAY));
  211. return IRQ_HANDLED;
  212. }
  213. /**************************************************************************
  214. * Interface to radio internal registers over top level marimba driver
  215. *************************************************************************/
  216. /*=============================================================================
  217. FUNCTION: tavarua_read_registers
  218. =============================================================================*/
  219. /**
  220. This function is called to read a number of bytes from an I2C interface.
  221. The bytes read are stored in internal register status (shadow copy).
  222. @param radio: structure pointer passed by client.
  223. @param offset: register offset.
  224. @param len: num of bytes.
  225. @return => 0 if successful.
  226. @return < 0 if failure.
  227. */
  228. static int tavarua_read_registers(struct tavarua_device *radio,
  229. unsigned char offset, int len)
  230. {
  231. int retval = 0, i = 0;
  232. if (unlikely(radio == NULL)) {
  233. FMDERR("%s:radio is null", __func__);
  234. return -EINVAL;
  235. }
  236. retval = set_fm_slave_id(radio);
  237. if (retval == -ENODEV)
  238. return retval;
  239. FMDBG_I2C("I2C Slave: %x, Read Offset(%x): Data [",
  240. radio->marimba->mod_id,
  241. offset);
  242. retval = marimba_read(radio->marimba, offset,
  243. &radio->registers[offset], len);
  244. if (retval > 0) {
  245. for (i = 0; i < len; i++)
  246. FMDBG_I2C("%02x ", radio->registers[offset+i]);
  247. FMDBG_I2C(" ]\n");
  248. }
  249. return retval;
  250. }
  251. /*=============================================================================
  252. FUNCTION: tavarua_write_register
  253. =============================================================================*/
  254. /**
  255. This function is called to write a byte over the I2C interface.
  256. The corresponding shadow copy is stored in internal register status.
  257. @param radio: structure pointer passed by client.
  258. @param offset: register offset.
  259. @param value: buffer to be written to the registers.
  260. @return => 0 if successful.
  261. @return < 0 if failure.
  262. */
  263. static int tavarua_write_register(struct tavarua_device *radio,
  264. unsigned char offset, unsigned char value)
  265. {
  266. int retval;
  267. if (unlikely(radio == NULL)) {
  268. FMDERR("%s:radio is null", __func__);
  269. return -EINVAL;
  270. }
  271. retval = set_fm_slave_id(radio);
  272. if (retval == -ENODEV)
  273. return retval;
  274. FMDBG_I2C("I2C Slave: %x, Write Offset(%x): Data[",
  275. radio->marimba->mod_id,
  276. offset);
  277. retval = marimba_write(radio->marimba, offset, &value, 1);
  278. if (retval > 0) {
  279. if (offset < RADIO_REGISTERS) {
  280. radio->registers[offset] = value;
  281. FMDBG_I2C("%02x ", radio->registers[offset]);
  282. }
  283. FMDBG_I2C(" ]\n");
  284. }
  285. return retval;
  286. }
  287. /*=============================================================================
  288. FUNCTION: tavarua_write_registers
  289. =============================================================================*/
  290. /**
  291. This function is called to write a number of bytes over the I2C interface.
  292. The corresponding shadow copy is stored in internal register status.
  293. @param radio: structure pointer passed by client.
  294. @param offset: register offset.
  295. @param buf: buffer to be written to the registers.
  296. @param len: num of bytes.
  297. @return => 0 if successful.
  298. @return < 0 if failure.
  299. */
  300. static int tavarua_write_registers(struct tavarua_device *radio,
  301. unsigned char offset, unsigned char *buf, int len)
  302. {
  303. int i;
  304. int retval;
  305. if (unlikely(radio == NULL)) {
  306. FMDERR("%s:radio is null", __func__);
  307. return -EINVAL;
  308. }
  309. retval = set_fm_slave_id(radio);
  310. if (retval == -ENODEV)
  311. return retval;
  312. FMDBG_I2C("I2C Slave: %x, Write Offset(%x): Data[",
  313. radio->marimba->mod_id,
  314. offset);
  315. retval = marimba_write(radio->marimba, offset, buf, len);
  316. if (retval > 0) { /* if write successful, update internal state too */
  317. for (i = 0; i < len; i++) {
  318. if ((offset+i) < RADIO_REGISTERS) {
  319. radio->registers[offset+i] = buf[i];
  320. FMDBG_I2C("%x ", radio->registers[offset+i]);
  321. }
  322. }
  323. FMDBG_I2C(" ]\n");
  324. }
  325. return retval;
  326. }
  327. /*=============================================================================
  328. FUNCTION: read_data_blocks
  329. =============================================================================*/
  330. /**
  331. This function reads Raw RDS blocks from Core regs to driver
  332. internal regs (shadow copy).
  333. @param radio: structure pointer passed by client.
  334. @param offset: register offset.
  335. @return => 0 if successful.
  336. @return < 0 if failure.
  337. */
  338. static int read_data_blocks(struct tavarua_device *radio, unsigned char offset)
  339. {
  340. if (unlikely(radio == NULL)) {
  341. FMDERR("%s:radio is null", __func__);
  342. return -EINVAL;
  343. }
  344. /* read all 3 RDS blocks */
  345. return tavarua_read_registers(radio, offset, RDS_BLOCK*4);
  346. }
  347. /*=============================================================================
  348. FUNCTION: tavarua_rds_read
  349. =============================================================================*/
  350. /**
  351. This is a rds processing function reads that reads Raw RDS blocks from Core
  352. regs to driver internal regs (shadow copy). It then fills the V4L2 RDS buffer,
  353. which is read by App using JNI interface.
  354. @param radio: structure pointer passed by client.
  355. @return None.
  356. */
  357. static void tavarua_rds_read(struct tavarua_device *radio)
  358. {
  359. struct kfifo *rds_buf;
  360. unsigned char blocknum;
  361. unsigned char tmp[3];
  362. if (unlikely(radio == NULL)) {
  363. FMDERR("%s:radio is null", __func__);
  364. return;
  365. }
  366. rds_buf = &radio->data_buf[TAVARUA_BUF_RAW_RDS];
  367. if (read_data_blocks(radio, RAW_RDS) < 0)
  368. return;
  369. /* copy all four RDS blocks to internal buffer */
  370. for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
  371. /* Fill the V4L2 RDS buffer */
  372. put_unaligned(cpu_to_le16(radio->registers[RAW_RDS +
  373. blocknum*RDS_BLOCK]), (unsigned short *) tmp);
  374. tmp[2] = blocknum; /* offset name */
  375. tmp[2] |= blocknum << 3; /* received offset */
  376. tmp[2] |= 0x40; /* corrected error(s) */
  377. /* copy RDS block to internal buffer */
  378. kfifo_in_locked(rds_buf, tmp, 3, &radio->buf_lock[TAVARUA_BUF_RAW_RDS]);
  379. }
  380. /* wake up read queue */
  381. if (kfifo_len(rds_buf))
  382. wake_up_interruptible(&radio->read_queue);
  383. }
  384. /*=============================================================================
  385. FUNCTION: request_read_xfr
  386. =============================================================================*/
  387. /**
  388. This function sets the desired MODE in the XFRCTRL register and also sets the
  389. CTRL field to read.
  390. This is an asynchronous way of reading the XFR registers. Client would request
  391. by setting the desired mode in the XFRCTRL register and then would initiate
  392. the actual data register read by calling copy_from_xfr up on SOC signals
  393. success.
  394. NOTE:
  395. The Data Transfer (XFR) registers are used to pass various data and
  396. configuration parameters between the Core and host processor.
  397. To read from the XFR registers, the host processor must set the desired MODE
  398. in the XFRCTRL register and set the CTRL field to read. The Core will then
  399. populate the XFRDAT0 - XFRDAT15 registers with the defined mode bytes. The
  400. Core will set the TRANSFER interrupt status bit and interrupt the host if the
  401. TRANSFERCTRL interrupt control bit is set. The host can then extract the XFR
  402. mode bytes once it detects that the Core has updated the registers.
  403. @param radio: structure pointer passed by client.
  404. @return Always returns 0.
  405. */
  406. static int request_read_xfr(struct tavarua_device *radio,
  407. enum tavarua_xfr_ctrl_t mode){
  408. if (unlikely(radio == NULL)) {
  409. FMDERR("%s:radio is null", __func__);
  410. return -EINVAL;
  411. }
  412. tavarua_write_register(radio, XFRCTRL, mode);
  413. msleep(TAVARUA_DELAY);
  414. return 0;
  415. }
  416. /*=============================================================================
  417. FUNCTION: copy_from_xfr
  418. =============================================================================*/
  419. /**
  420. This function is used to read XFR mode bytes once it detects that the Core
  421. has updated the registers. It also updates XFR regs to the appropriate
  422. internal buffer n bytes.
  423. NOTE:
  424. This function should be used in conjuction with request_read_xfr. Refer
  425. request_read_xfr for XFR mode transaction details.
  426. @param radio: structure pointer passed by client.
  427. @param buf_type: Index into RDS/Radio event buffer to use.
  428. @param len: num of bytes.
  429. @return Always returns 0.
  430. */
  431. static int copy_from_xfr(struct tavarua_device *radio,
  432. enum tavarua_buf_t buf_type, unsigned int n){
  433. struct kfifo *data_fifo;
  434. unsigned char *xfr_regs;
  435. if (unlikely(radio == NULL)) {
  436. FMDERR("%s:radio is null", __func__);
  437. return -EINVAL;
  438. }
  439. data_fifo = &radio->data_buf[buf_type];
  440. xfr_regs = &radio->registers[XFRCTRL+1];
  441. kfifo_in_locked(data_fifo, xfr_regs, n, &radio->buf_lock[buf_type]);
  442. return 0;
  443. }
  444. /*=============================================================================
  445. FUNCTION: write_to_xfr
  446. =============================================================================*/
  447. /**
  448. This function sets the desired MODE in the XFRCTRL register and it also sets
  449. the CTRL field and data to write.
  450. This also writes all the XFRDATx registers with the desired input buffer.
  451. NOTE:
  452. The Data Transfer (XFR) registers are used to pass various data and
  453. configuration parameters between the Core and host processor.
  454. To write data to the Core, the host processor updates XFRDAT0 - XFRDAT15 with
  455. the appropriate mode bytes. The host processor must then set the desired MODE
  456. in the XFRCTRL register and set the CTRL field to write. The core will detect
  457. that the XFRCTRL register was written to and will read the XFR mode bytes.
  458. After reading all the mode bytes, the Core will set the TRANSFER interrupt
  459. status bit and interrupt the host if the TRANSFERCTRL interrupt control bit
  460. is set.
  461. @param radio: structure pointer passed by client.
  462. @param mode: XFR mode to write in XFRCTRL register.
  463. @param buf: buffer to be written to the registers.
  464. @param len: num of bytes.
  465. @return => 0 if successful.
  466. @return < 0 if failure.
  467. */
  468. static int write_to_xfr(struct tavarua_device *radio, unsigned char mode,
  469. char *buf, int len)
  470. {
  471. char buffer[len+1];
  472. if (unlikely(radio == NULL)) {
  473. FMDERR("%s:radio is null", __func__);
  474. return -EINVAL;
  475. }
  476. memcpy(buffer+1, buf, len);
  477. /* buffer[0] corresponds to XFRCTRL register
  478. set the CTRL bit to 1 for write mode
  479. */
  480. buffer[0] = ((1<<7) | mode);
  481. return tavarua_write_registers(radio, XFRCTRL, buffer, sizeof(buffer));
  482. }
  483. /*=============================================================================
  484. FUNCTION: xfr_intf_own
  485. =============================================================================*/
  486. /**
  487. This function is used to check if there is any pending XFR mode operation.
  488. If yes, wait for it to complete, else update the flag to indicate XFR
  489. operation is in progress
  490. @param radio: structure pointer passed by client.
  491. @return 0 on success.
  492. -ETIME on timeout.
  493. */
  494. static int xfr_intf_own(struct tavarua_device *radio)
  495. {
  496. if (unlikely(radio == NULL)) {
  497. FMDERR("%s:radio is null", __func__);
  498. return -EINVAL;
  499. }
  500. mutex_lock(&radio->lock);
  501. if (radio->xfr_in_progress) {
  502. radio->pending_xfrs[TAVARUA_XFR_SYNC] = 1;
  503. mutex_unlock(&radio->lock);
  504. if (!wait_for_completion_timeout(&radio->sync_xfr_start,
  505. msecs_to_jiffies(wait_timeout)))
  506. return -ETIME;
  507. } else {
  508. FMDBG("gained ownership of xfr\n");
  509. radio->xfr_in_progress = 1;
  510. mutex_unlock(&radio->lock);
  511. }
  512. return 0;
  513. }
  514. /*=============================================================================
  515. FUNCTION: sync_read_xfr
  516. =============================================================================*/
  517. /**
  518. This function is used to do synchronous XFR read operation.
  519. @param radio: structure pointer passed by client.
  520. @param xfr_type: XFR mode to write in XFRCTRL register.
  521. @param buf: buffer to be read from the core.
  522. @return => 0 if successful.
  523. @return < 0 if failure.
  524. */
  525. static int sync_read_xfr(struct tavarua_device *radio,
  526. enum tavarua_xfr_ctrl_t xfr_type, unsigned char *buf)
  527. {
  528. int retval;
  529. if (unlikely(radio == NULL)) {
  530. FMDERR("%s:radio is null", __func__);
  531. return -EINVAL;
  532. }
  533. retval = xfr_intf_own(radio);
  534. if (retval < 0)
  535. return retval;
  536. retval = tavarua_write_register(radio, XFRCTRL, xfr_type);
  537. if (retval >= 0) {
  538. /* Wait for interrupt i.e. complete
  539. (&radio->sync_req_done); call */
  540. if (!wait_for_completion_timeout(&radio->sync_req_done,
  541. msecs_to_jiffies(wait_timeout)) || (retval < 0)) {
  542. retval = -ETIME;
  543. } else {
  544. memcpy(buf, radio->sync_xfr_regs, XFR_REG_NUM);
  545. }
  546. }
  547. radio->xfr_in_progress = 0;
  548. start_pending_xfr(radio);
  549. FMDBG("%s: %d\n", __func__, retval);
  550. return retval;
  551. }
  552. /*=============================================================================
  553. FUNCTION: sync_write_xfr
  554. =============================================================================*/
  555. /**
  556. This function is used to do synchronous XFR write operation.
  557. @param radio: structure pointer passed by client.
  558. @param xfr_type: XFR mode to write in XFRCTRL register.
  559. @param buf: buffer to be written to the core.
  560. @return => 0 if successful.
  561. @return < 0 if failure.
  562. */
  563. static int sync_write_xfr(struct tavarua_device *radio,
  564. enum tavarua_xfr_ctrl_t xfr_type, unsigned char *buf)
  565. {
  566. int retval;
  567. if (unlikely(radio == NULL)) {
  568. FMDERR("%s:radio is null", __func__);
  569. return -EINVAL;
  570. }
  571. if (unlikely(buf == NULL)) {
  572. FMDERR("%s:buf is null", __func__);
  573. return -EINVAL;
  574. }
  575. retval = xfr_intf_own(radio);
  576. if (retval < 0)
  577. return retval;
  578. retval = write_to_xfr(radio, xfr_type, buf, XFR_REG_NUM);
  579. if (retval >= 0) {
  580. /* Wait for interrupt i.e. complete
  581. (&radio->sync_req_done); call */
  582. if (!wait_for_completion_timeout(&radio->sync_req_done,
  583. msecs_to_jiffies(wait_timeout)) || (retval < 0)) {
  584. FMDBG("Write xfr timeout");
  585. }
  586. }
  587. radio->xfr_in_progress = 0;
  588. start_pending_xfr(radio);
  589. FMDBG("%s: %d\n", __func__, retval);
  590. return retval;
  591. }
  592. /*=============================================================================
  593. FUNCTION: start_pending_xfr
  594. =============================================================================*/
  595. /**
  596. This function checks if their are any pending xfr interrupts and if
  597. the interrupts are either RDS PS, RDS RT, RDS AF, SCANNEXT, SEARCH or SYNC
  598. then initiates corresponding read operation. Preference is given to RAW RDS
  599. data (SYNC) over processed data (PS, RT, AF, etc) from core.
  600. @param radio: structure pointer passed by client.
  601. @return None.
  602. */
  603. static void start_pending_xfr(struct tavarua_device *radio)
  604. {
  605. int i;
  606. enum tavarua_xfr_t xfr;
  607. if (unlikely(radio == NULL)) {
  608. FMDERR("%s:radio is null", __func__);
  609. return;
  610. }
  611. for (i = 0; i < TAVARUA_XFR_MAX; i++) {
  612. if (radio->pending_xfrs[i]) {
  613. radio->xfr_in_progress = 1;
  614. xfr = (enum tavarua_xfr_t)i;
  615. switch (xfr) {
  616. /* priority given to synchronous xfrs */
  617. case TAVARUA_XFR_SYNC:
  618. complete(&radio->sync_xfr_start);
  619. break;
  620. /* asynchrnous xfrs */
  621. case TAVARUA_XFR_SRCH_LIST:
  622. request_read_xfr(radio, RX_STATIONS_0);
  623. break;
  624. case TAVARUA_XFR_RT_RDS:
  625. request_read_xfr(radio, RDS_RT_0);
  626. break;
  627. case TAVARUA_XFR_PS_RDS:
  628. request_read_xfr(radio, RDS_PS_0);
  629. break;
  630. case TAVARUA_XFR_AF_LIST:
  631. request_read_xfr(radio, RDS_AF_0);
  632. break;
  633. default:
  634. FMDERR("%s: Unsupported XFR %d\n",
  635. __func__, xfr);
  636. }
  637. radio->pending_xfrs[i] = 0;
  638. FMDBG("resurrect xfr %d\n", i);
  639. }
  640. }
  641. return;
  642. }
  643. /*=============================================================================
  644. FUNCTION: tavarua_q_event
  645. =============================================================================*/
  646. /**
  647. This function is called to queue an event for user.
  648. NOTE:
  649. Applications call the VIDIOC_QBUF ioctl to enqueue an empty (capturing) or
  650. filled (output) buffer in the driver's incoming queue.
  651. Pleaes refer tavarua_probe where we register different ioctl's for FM.
  652. @param radio: structure pointer passed by client.
  653. @param event: event to be queued.
  654. @return None.
  655. */
  656. static void tavarua_q_event(struct tavarua_device *radio,
  657. enum tavarua_evt_t event)
  658. {
  659. struct kfifo *data_b;
  660. unsigned char evt = event;
  661. if (unlikely(radio == NULL)) {
  662. FMDERR("%s:radio is null", __func__);
  663. return;
  664. }
  665. data_b = &radio->data_buf[TAVARUA_BUF_EVENTS];
  666. FMDBG("updating event_q with event %x\n", event);
  667. if (kfifo_in_locked(data_b, &evt, 1, &radio->buf_lock[TAVARUA_BUF_EVENTS]))
  668. wake_up_interruptible(&radio->event_queue);
  669. }
  670. /*=============================================================================
  671. FUNCTION: tavarua_start_xfr
  672. =============================================================================*/
  673. /**
  674. This function is called to process interrupts which require multiple XFR
  675. operations (RDS search, RDS PS, RDS RT, etc). if any XFR operation is
  676. already in progress we store information about pending interrupt, which
  677. will be processed in future when current pending operation is done.
  678. @param radio: structure pointer passed by client.
  679. @param pending_id: XFR operation (which requires multiple XFR operations in
  680. steps) to start.
  681. @param xfr_id: XFR mode to write in XFRCTRL register.
  682. @return None.
  683. */
  684. static void tavarua_start_xfr(struct tavarua_device *radio,
  685. enum tavarua_xfr_t pending_id, enum tavarua_xfr_ctrl_t xfr_id)
  686. {
  687. if (unlikely(radio == NULL)) {
  688. FMDERR("%s:radio is null", __func__);
  689. return;
  690. }
  691. if (radio->xfr_in_progress)
  692. radio->pending_xfrs[pending_id] = 1;
  693. else {
  694. radio->xfr_in_progress = 1;
  695. request_read_xfr(radio, xfr_id);
  696. }
  697. }
  698. /*=============================================================================
  699. FUNCTION: tavarua_handle_interrupts
  700. =============================================================================*/
  701. /**
  702. This function processes the interrupts.
  703. NOTE:
  704. tavarua_q_event is used to queue events in App buffer. i.e. App calls the
  705. VIDIOC_QBUF ioctl to enqueue an empty (capturing) buffer, which is filled
  706. by tavarua_q_event call.
  707. Any async event that requires multiple steps, i.e. search, RT, PS, etc is
  708. handled one at a time. (We preserve other interrupts when processing one).
  709. Sync interrupts are given priority.
  710. @param radio: structure pointer passed by client.
  711. @return None.
  712. */
  713. static void tavarua_handle_interrupts(struct tavarua_device *radio)
  714. {
  715. int i;
  716. int retval, adj_channel_tune_req = 0;
  717. unsigned char xfr_status;
  718. if (unlikely(radio == NULL)) {
  719. FMDERR("%s:radio is null", __func__);
  720. return;
  721. }
  722. if (!radio->handle_irq) {
  723. FMDBG("IRQ happend, but I wont handle it\n");
  724. return;
  725. }
  726. mutex_lock(&radio->lock);
  727. retval = tavarua_read_registers(radio, STATUS_REG1, STATUS_REG_NUM);
  728. if (retval < 0) {
  729. FMDERR("Fails to read status register and try once again");
  730. msleep(TAVARUA_DELAY);
  731. retval = tavarua_read_registers(radio, STATUS_REG1,
  732. STATUS_REG_NUM);
  733. if (retval < 0)
  734. FMDERR("Fails to read status register");
  735. }
  736. FMDBG("INTSTAT1 <%x>\n", radio->registers[STATUS_REG1]);
  737. FMDBG("INTSTAT2 <%x>\n", radio->registers[STATUS_REG2]);
  738. FMDBG("INTSTAT3 <%x>\n", radio->registers[STATUS_REG3]);
  739. if (radio->registers[STATUS_REG1] & READY) {
  740. complete(&radio->sync_req_done);
  741. tavarua_q_event(radio, TAVARUA_EVT_RADIO_READY);
  742. }
  743. /* Tune completed */
  744. if (radio->registers[STATUS_REG1] & TUNE) {
  745. if (radio->tune_req) {
  746. complete(&radio->sync_req_done);
  747. radio->tune_req = 0;
  748. }
  749. /*
  750. * Do not queue the TUNE event while validating if the station
  751. * is good or not. As part of channel validation we tune to the
  752. * adjacent station, measure its MPX_DCC value, then tune back
  753. * to the original station and measure its MPX_DCC value.
  754. * Compare the MPX_DCC values of curent and adjacent stations
  755. * and decide if the channel is valid or not. During this period
  756. * we should not queue the TUNE event to the upper layers.
  757. */
  758. adj_channel_tune_req = atomic_read(&radio->validate_channel);
  759. if (adj_channel_tune_req) {
  760. complete(&radio->sync_req_done);
  761. FMDBG("Tune event for adjacent channel\n");
  762. } else {
  763. tavarua_q_event(radio, TAVARUA_EVT_TUNE_SUCC);
  764. FMDBG("Queueing Tune event\n");
  765. }
  766. if (radio->srch_params.get_list) {
  767. tavarua_start_xfr(radio, TAVARUA_XFR_SRCH_LIST,
  768. RX_STATIONS_0);
  769. }
  770. radio->srch_params.get_list = 0;
  771. radio->xfr_in_progress = 0;
  772. radio->xfr_bytes_left = 0;
  773. for (i = 0; i < TAVARUA_BUF_MAX; i++) {
  774. if (i >= TAVARUA_BUF_RT_RDS)
  775. kfifo_reset(&radio->data_buf[i]);
  776. }
  777. for (i = 0; i < TAVARUA_XFR_MAX; i++) {
  778. if (i >= TAVARUA_XFR_RT_RDS)
  779. radio->pending_xfrs[i] = 0;
  780. }
  781. retval = tavarua_read_registers(radio, TUNECTRL, 1);
  782. /* send to user station parameters */
  783. if (retval > -1) {
  784. /* Signal strength */
  785. if (!(radio->registers[TUNECTRL] & SIGSTATE))
  786. tavarua_q_event(radio, TAVARUA_EVT_BELOW_TH);
  787. else
  788. tavarua_q_event(radio, TAVARUA_EVT_ABOVE_TH);
  789. /* mono/stereo */
  790. if ((radio->registers[TUNECTRL] & MOSTSTATE))
  791. tavarua_q_event(radio, TAVARUA_EVT_STEREO);
  792. else
  793. tavarua_q_event(radio, TAVARUA_EVT_MONO);
  794. /* is RDS available */
  795. if ((radio->registers[TUNECTRL] & RDSSYNC))
  796. tavarua_q_event(radio, TAVARUA_EVT_RDS_AVAIL);
  797. else
  798. tavarua_q_event(radio,
  799. TAVARUA_EVT_RDS_NOT_AVAIL);
  800. }
  801. } else {
  802. if (radio->tune_req) {
  803. FMDERR("Tune INT is pending\n");
  804. mutex_unlock(&radio->lock);
  805. return;
  806. }
  807. }
  808. /* Search completed (read FREQ) */
  809. if (radio->registers[STATUS_REG1] & SEARCH)
  810. tavarua_q_event(radio, TAVARUA_EVT_SEEK_COMPLETE);
  811. /* Scanning for next station */
  812. if (radio->registers[STATUS_REG1] & SCANNEXT)
  813. tavarua_q_event(radio, TAVARUA_EVT_SCAN_NEXT);
  814. /* Signal indicator change (read SIGSTATE) */
  815. if (radio->registers[STATUS_REG1] & SIGNAL) {
  816. retval = tavarua_read_registers(radio, TUNECTRL, 1);
  817. if (retval > -1) {
  818. if (!(radio->registers[TUNECTRL] & SIGSTATE))
  819. tavarua_q_event(radio, TAVARUA_EVT_BELOW_TH);
  820. else
  821. tavarua_q_event(radio, TAVARUA_EVT_ABOVE_TH);
  822. }
  823. }
  824. /* RDS synchronization state change (read RDSSYNC) */
  825. if (radio->registers[STATUS_REG1] & SYNC) {
  826. retval = tavarua_read_registers(radio, TUNECTRL, 1);
  827. if (retval > -1) {
  828. if ((radio->registers[TUNECTRL] & RDSSYNC))
  829. tavarua_q_event(radio, TAVARUA_EVT_RDS_AVAIL);
  830. else
  831. tavarua_q_event(radio,
  832. TAVARUA_EVT_RDS_NOT_AVAIL);
  833. }
  834. }
  835. /* Audio Control indicator (read AUDIOIND) */
  836. if (radio->registers[STATUS_REG1] & AUDIO) {
  837. retval = tavarua_read_registers(radio, AUDIOIND, 1);
  838. if (retval > -1) {
  839. if ((radio->registers[AUDIOIND] & 0x01))
  840. tavarua_q_event(radio, TAVARUA_EVT_STEREO);
  841. else
  842. tavarua_q_event(radio, TAVARUA_EVT_MONO);
  843. }
  844. }
  845. /* interrupt register 2 */
  846. /* New unread RDS data group available */
  847. if (radio->registers[STATUS_REG2] & RDSDAT) {
  848. FMDBG("Raw RDS Available\n");
  849. tavarua_rds_read(radio);
  850. tavarua_q_event(radio, TAVARUA_EVT_NEW_RAW_RDS);
  851. }
  852. /* New RDS Program Service Table available */
  853. if (radio->registers[STATUS_REG2] & RDSPS) {
  854. FMDBG("New PS RDS\n");
  855. tavarua_start_xfr(radio, TAVARUA_XFR_PS_RDS, RDS_PS_0);
  856. }
  857. /* New RDS Radio Text available */
  858. if (radio->registers[STATUS_REG2] & RDSRT) {
  859. FMDBG("New RT RDS\n");
  860. tavarua_start_xfr(radio, TAVARUA_XFR_RT_RDS, RDS_RT_0);
  861. }
  862. /* New RDS Radio Text available */
  863. if (radio->registers[STATUS_REG2] & RDSAF) {
  864. FMDBG("New AF RDS\n");
  865. tavarua_start_xfr(radio, TAVARUA_XFR_AF_LIST, RDS_AF_0);
  866. }
  867. /* Trasmitter an RDS Group */
  868. if (radio->registers[STATUS_REG2] & TXRDSDAT) {
  869. FMDBG("New TXRDSDAT\n");
  870. tavarua_q_event(radio, TAVARUA_EVT_TXRDSDAT);
  871. }
  872. /* Complete RDS buffer is available for transmission */
  873. if (radio->registers[STATUS_REG2] & TXRDSDONE) {
  874. FMDBG("New TXRDSDAT\n");
  875. tavarua_q_event(radio, TAVARUA_EVT_TXRDSDONE);
  876. }
  877. /* interrupt register 3 */
  878. /* Data transfer (XFR) completed */
  879. if (radio->registers[STATUS_REG3] & TRANSFER) {
  880. FMDBG("XFR Interrupt\n");
  881. tavarua_read_registers(radio, XFRCTRL, XFR_REG_NUM+1);
  882. FMDBG("XFRCTRL IS: %x\n", radio->registers[XFRCTRL]);
  883. xfr_status = radio->registers[XFRCTRL];
  884. switch (xfr_status) {
  885. case RDS_PS_0:
  886. FMDBG("PS Header\n");
  887. copy_from_xfr(radio, TAVARUA_BUF_PS_RDS, 5);
  888. radio->xfr_bytes_left = (radio->registers[XFRCTRL+1] &
  889. 0x0F) * 8;
  890. FMDBG("PS RDS Length: %d\n", radio->xfr_bytes_left);
  891. if ((radio->xfr_bytes_left > 0) &&
  892. (radio->xfr_bytes_left < 97))
  893. request_read_xfr(radio, RDS_PS_1);
  894. else
  895. radio->xfr_in_progress = 0;
  896. break;
  897. case RDS_PS_1:
  898. case RDS_PS_2:
  899. case RDS_PS_3:
  900. case RDS_PS_4:
  901. case RDS_PS_5:
  902. case RDS_PS_6:
  903. FMDBG("PS Data\n");
  904. copy_from_xfr(radio, TAVARUA_BUF_PS_RDS, XFR_REG_NUM);
  905. radio->xfr_bytes_left -= XFR_REG_NUM;
  906. if (radio->xfr_bytes_left > 0) {
  907. if ((xfr_status + 1) > RDS_PS_6)
  908. request_read_xfr(radio, RDS_PS_6);
  909. else
  910. request_read_xfr(radio, xfr_status+1);
  911. } else {
  912. radio->xfr_in_progress = 0;
  913. tavarua_q_event(radio, TAVARUA_EVT_NEW_PS_RDS);
  914. }
  915. break;
  916. case RDS_RT_0:
  917. FMDBG("RT Header\n");
  918. copy_from_xfr(radio, TAVARUA_BUF_RT_RDS, 5);
  919. radio->xfr_bytes_left = radio->registers[XFRCTRL+1]
  920. & 0x7F;
  921. FMDBG("RT RDS Length: %d\n", radio->xfr_bytes_left);
  922. /*RT_1 to RT_4 16 byte registers so 64 bytes */
  923. if ((radio->xfr_bytes_left > 0)
  924. && (radio->xfr_bytes_left < 65))
  925. request_read_xfr(radio, RDS_RT_1);
  926. break;
  927. case RDS_RT_1:
  928. case RDS_RT_2:
  929. case RDS_RT_3:
  930. case RDS_RT_4:
  931. FMDBG("xfr interrupt RT data\n");
  932. copy_from_xfr(radio, TAVARUA_BUF_RT_RDS, XFR_REG_NUM);
  933. radio->xfr_bytes_left -= XFR_REG_NUM;
  934. if (radio->xfr_bytes_left > 0)
  935. request_read_xfr(radio, xfr_status+1);
  936. else {
  937. radio->xfr_in_progress = 0;
  938. tavarua_q_event(radio, TAVARUA_EVT_NEW_RT_RDS);
  939. }
  940. break;
  941. case RDS_AF_0:
  942. copy_from_xfr(radio, TAVARUA_BUF_AF_LIST,
  943. XFR_REG_NUM);
  944. radio->xfr_bytes_left = radio->registers[XFRCTRL+5]-11;
  945. if (radio->xfr_bytes_left > 0)
  946. request_read_xfr(radio, RDS_AF_1);
  947. else
  948. radio->xfr_in_progress = 0;
  949. break;
  950. case RDS_AF_1:
  951. copy_from_xfr(radio, TAVARUA_BUF_AF_LIST,
  952. radio->xfr_bytes_left);
  953. tavarua_q_event(radio, TAVARUA_EVT_NEW_AF_LIST);
  954. radio->xfr_in_progress = 0;
  955. break;
  956. case RX_CONFIG:
  957. case RADIO_CONFIG:
  958. case RDS_CONFIG:
  959. memcpy(radio->sync_xfr_regs,
  960. &radio->registers[XFRCTRL+1], XFR_REG_NUM);
  961. complete(&radio->sync_req_done);
  962. break;
  963. case RX_STATIONS_0:
  964. FMDBG("Search list has %d stations\n",
  965. radio->registers[XFRCTRL+1]);
  966. radio->xfr_bytes_left = radio->registers[XFRCTRL+1]*2;
  967. if (!radio->registers[XFRCTRL+1]) {
  968. copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
  969. 1);
  970. tavarua_q_event(radio,
  971. TAVARUA_EVT_NEW_SRCH_LIST);
  972. radio->xfr_in_progress = 0;
  973. } else if (radio->xfr_bytes_left > 14) {
  974. copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
  975. RX_STATIONS0_LEN);
  976. request_read_xfr(radio, RX_STATIONS_1);
  977. } else if (radio->xfr_bytes_left) {
  978. FMDBG("In else RX_STATIONS_0\n");
  979. copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
  980. radio->xfr_bytes_left+1);
  981. tavarua_q_event(radio,
  982. TAVARUA_EVT_NEW_SRCH_LIST);
  983. radio->xfr_in_progress = 0;
  984. }
  985. break;
  986. case RX_STATIONS_1:
  987. FMDBG("In RX_STATIONS_1");
  988. copy_from_xfr(radio, TAVARUA_BUF_SRCH_LIST,
  989. radio->xfr_bytes_left);
  990. tavarua_q_event(radio, TAVARUA_EVT_NEW_SRCH_LIST);
  991. radio->xfr_in_progress = 0;
  992. break;
  993. case PHY_TXGAIN:
  994. FMDBG("read PHY_TXGAIN is successful");
  995. complete(&radio->sync_req_done);
  996. break;
  997. case (XFR_EXT | 0x80):
  998. FMDBG("Set tone generator successful\n");
  999. complete(&radio->sync_req_done);
  1000. break;
  1001. case (0x80 | RX_CONFIG):
  1002. case (0x80 | RADIO_CONFIG):
  1003. case (0x80 | RDS_CONFIG):
  1004. case (0x80 | INT_CTRL):
  1005. complete(&radio->sync_req_done);
  1006. break;
  1007. case (0x80 | RDS_RT_0):
  1008. FMDBG("RT Header Sent\n");
  1009. complete(&radio->sync_req_done);
  1010. break;
  1011. case (0x80 | RDS_RT_1):
  1012. case (0x80 | RDS_RT_2):
  1013. case (0x80 | RDS_RT_3):
  1014. case (0x80 | RDS_RT_4):
  1015. FMDBG("xfr interrupt RT data Sent\n");
  1016. complete(&radio->sync_req_done);
  1017. break;
  1018. /*TX Specific transfer */
  1019. case (0x80 | RDS_PS_0):
  1020. FMDBG("PS Header Sent\n");
  1021. complete(&radio->sync_req_done);
  1022. break;
  1023. case (0x80 | RDS_PS_1):
  1024. case (0x80 | RDS_PS_2):
  1025. case (0x80 | RDS_PS_3):
  1026. case (0x80 | RDS_PS_4):
  1027. case (0x80 | RDS_PS_5):
  1028. case (0x80 | RDS_PS_6):
  1029. FMDBG("xfr interrupt PS data Sent\n");
  1030. complete(&radio->sync_req_done);
  1031. break;
  1032. case (0x80 | PHY_TXGAIN):
  1033. FMDBG("write PHY_TXGAIN is successful");
  1034. complete(&radio->sync_req_done);
  1035. break;
  1036. case (XFR_POKE_COMPLETE | LSH_DATA(ONE_BYTE, 1)):
  1037. case (XFR_POKE_COMPLETE | LSH_DATA(TWO_BYTE, 1)):
  1038. case (XFR_POKE_COMPLETE | LSH_DATA(THREE_BYTE, 1)):
  1039. case (XFR_POKE_COMPLETE | LSH_DATA(FOUR_BYTE, 1)):
  1040. case (XFR_POKE_COMPLETE | LSH_DATA(FIVE_BYTE, 1)):
  1041. case (XFR_POKE_COMPLETE | LSH_DATA(SIX_BYTE, 1)):
  1042. case (XFR_POKE_COMPLETE | LSH_DATA(SEVEN_BYTE, 1)):
  1043. case (XFR_POKE_COMPLETE | LSH_DATA(EIGHT_BYTE, 1)):
  1044. case (XFR_POKE_COMPLETE | LSH_DATA(NINE_BYTE, 1)):
  1045. case (XFR_POKE_COMPLETE | LSH_DATA(TEN_BYTE, 1)):
  1046. case (XFR_POKE_COMPLETE | LSH_DATA(ELEVEN_BYTE, 1)):
  1047. case (XFR_POKE_COMPLETE | LSH_DATA(TWELVE_BYTE, 1)):
  1048. case (XFR_POKE_COMPLETE | LSH_DATA(THIRTEEN_BYTE, 1)):
  1049. case (XFR_PEEK_COMPLETE | LSH_DATA(ONE_BYTE, 1)):
  1050. case (XFR_PEEK_COMPLETE | LSH_DATA(TWO_BYTE, 1)):
  1051. case (XFR_PEEK_COMPLETE | LSH_DATA(THREE_BYTE, 1)):
  1052. case (XFR_PEEK_COMPLETE | LSH_DATA(FOUR_BYTE, 1)):
  1053. case (XFR_PEEK_COMPLETE | LSH_DATA(FIVE_BYTE, 1)):
  1054. case (XFR_PEEK_COMPLETE | LSH_DATA(SIX_BYTE, 1)):
  1055. case (XFR_PEEK_COMPLETE | LSH_DATA(SEVEN_BYTE, 1)):
  1056. case (XFR_PEEK_COMPLETE | LSH_DATA(EIGHT_BYTE, 1)):
  1057. case (XFR_PEEK_COMPLETE | LSH_DATA(NINE_BYTE, 1)):
  1058. case (XFR_PEEK_COMPLETE | LSH_DATA(TEN_BYTE, 1)):
  1059. case (XFR_PEEK_COMPLETE | LSH_DATA(ELEVEN_BYTE, 1)):
  1060. case (XFR_PEEK_COMPLETE | LSH_DATA(TWELVE_BYTE, 1)):
  1061. case (XFR_PEEK_COMPLETE | LSH_DATA(THIRTEEN_BYTE, 1)):
  1062. FMDBG("XFR interrupt for PEEK/POKE complete\n");
  1063. complete(&radio->sync_req_done);
  1064. break;
  1065. default:
  1066. FMDERR("UNKNOWN XFR = %d\n", xfr_status);
  1067. }
  1068. if (!radio->xfr_in_progress)
  1069. start_pending_xfr(radio);
  1070. }
  1071. /* Error occurred. Read ERRCODE to determine cause */
  1072. if (radio->registers[STATUS_REG3] & ERROR) {
  1073. #ifdef FM_DEBUG
  1074. unsigned char xfr_buf[XFR_REG_NUM];
  1075. int retval = sync_read_xfr(radio, ERROR_CODE, xfr_buf);
  1076. FMDBG("retval of ERROR_CODE read : %d\n", retval);
  1077. #endif
  1078. FMDERR("ERROR STATE\n");
  1079. }
  1080. mutex_unlock(&radio->lock);
  1081. FMDBG("Work is done\n");
  1082. }
  1083. /*=============================================================================
  1084. FUNCTION: read_int_stat
  1085. =============================================================================*/
  1086. /**
  1087. This function is scheduled whenever there is an interrupt pending in interrupt
  1088. queue. i.e. kfmradio.
  1089. Whenever there is a GPIO interrupt, a delayed work will be queued in to the
  1090. 'kfmradio' work queue. Upon execution of this work in the queue, a a call
  1091. to read_int_stat function will be made , which would in turn handle the
  1092. interrupts by reading the INTSTATx registers.
  1093. NOTE:
  1094. Tasks to be run out of a workqueue need to be packaged in a struct
  1095. work_struct structure.
  1096. @param work: work_struct structure.
  1097. @return None.
  1098. */
  1099. static void read_int_stat(struct work_struct *work)
  1100. {
  1101. struct tavarua_device *radio;
  1102. if (unlikely(work == NULL)) {
  1103. FMDERR("%s:work is null", __func__);
  1104. return;
  1105. }
  1106. radio = container_of(work, struct tavarua_device, work.work);
  1107. tavarua_handle_interrupts(radio);
  1108. }
  1109. static void fm_shutdown(struct work_struct *work)
  1110. {
  1111. struct tavarua_device *radio;
  1112. if (unlikely(work == NULL)) {
  1113. FMDERR("%s:work is null", __func__);
  1114. return;
  1115. }
  1116. radio = container_of(work, struct tavarua_device, work.work);
  1117. if (unlikely(radio == NULL)) {
  1118. FMDERR("%s:radio is null", __func__);
  1119. return;
  1120. }
  1121. FMDERR("%s: Releasing the FM I2S GPIO\n", __func__);
  1122. if (radio->pdata->config_i2s_gpio != NULL)
  1123. radio->pdata->config_i2s_gpio(FM_I2S_OFF);
  1124. FMDERR("%s: Shutting down FM SOC\n", __func__);
  1125. radio->pdata->fm_shutdown(radio->pdata);
  1126. complete(&radio->shutdown_done);
  1127. }
  1128. /*************************************************************************
  1129. * irq helper functions
  1130. ************************************************************************/
  1131. /*=============================================================================
  1132. FUNCTION: tavarua_request_irq
  1133. =============================================================================*/
  1134. /**
  1135. This function is called to acquire a FM GPIO and enable FM interrupts.
  1136. @param radio: structure pointer passed by client.
  1137. @return 0 if success else otherwise.
  1138. */
  1139. static int tavarua_request_irq(struct tavarua_device *radio)
  1140. {
  1141. int retval;
  1142. int irq;
  1143. if (unlikely(radio == NULL)) {
  1144. FMDERR("%s:radio is null", __func__);
  1145. return -EINVAL;
  1146. }
  1147. irq = radio->pdata->irq;
  1148. /* A workqueue created with create_workqueue() will have one worker thread
  1149. * for each CPU on the system; create_singlethread_workqueue(), instead,
  1150. * creates a workqueue with a single worker process. The name of the queue
  1151. * is limited to ten characters; it is only used for generating the "command"
  1152. * for the kernel thread(s) (which can be seen in ps or top).
  1153. */
  1154. /* allocate an interrupt line */
  1155. /* On success, request_irq() returns 0 if everything goes as
  1156. planned. Your interrupt handler will start receiving its
  1157. interrupts immediately. On failure, request_irq()
  1158. returns:
  1159. -EINVAL
  1160. The IRQ number you requested was either
  1161. invalid or reserved, or your passed a NULL
  1162. pointer for the handler() parameter.
  1163. -EBUSY The IRQ you requested is already being
  1164. handled, and the IRQ cannot be shared.
  1165. -ENXIO The m68k returns this value for an invalid
  1166. IRQ number.
  1167. */
  1168. /* Use request_any_context_irq, So that it might work for nested or
  1169. nested interrupts. in MSM8x60, FM is connected to PMIC GPIO and it
  1170. is a nested interrupt*/
  1171. retval = request_any_context_irq(irq, tavarua_isr,
  1172. IRQ_TYPE_EDGE_FALLING, "fm interrupt", radio);
  1173. if (retval < 0) {
  1174. FMDERR("Couldn't acquire FM gpio %d\n", irq);
  1175. return retval;
  1176. } else {
  1177. FMDBG("FM GPIO %d registered\n", irq);
  1178. }
  1179. retval = enable_irq_wake(irq);
  1180. if (retval < 0) {
  1181. FMDERR("Could not enable FM interrupt\n ");
  1182. free_irq(irq , radio);
  1183. }
  1184. return retval;
  1185. }
  1186. /*=============================================================================
  1187. FUNCTION: tavarua_disable_irq
  1188. =============================================================================*/
  1189. /**
  1190. This function is called to disable FM irq and free up FM interrupt handling
  1191. resources.
  1192. @param radio: structure pointer passed by client.
  1193. @return 0 if success else otherwise.
  1194. */
  1195. static int tavarua_disable_irq(struct tavarua_device *radio)
  1196. {
  1197. int irq;
  1198. if (unlikely(radio == NULL)) {
  1199. FMDERR("%s:radio is null", __func__);
  1200. return -EINVAL;
  1201. }
  1202. irq = radio->pdata->irq;
  1203. disable_irq_wake(irq);
  1204. free_irq(irq, radio);
  1205. cancel_delayed_work_sync(&radio->work);
  1206. flush_workqueue(radio->wqueue);
  1207. return 0;
  1208. }
  1209. static int optimized_search_algorithm(struct tavarua_device *radio,
  1210. int region)
  1211. {
  1212. unsigned char adie_type_bahma;
  1213. int retval = 0;
  1214. unsigned int rdsMask = 0;
  1215. unsigned char value = 0;
  1216. if (unlikely(radio == NULL)) {
  1217. FMDERR("%s:radio is null", __func__);
  1218. return -EINVAL;
  1219. }
  1220. adie_type_bahma = is_bahama();
  1221. switch (region) {
  1222. case TAVARUA_REGION_US:
  1223. /*
  1224. Radio band for all the 200KHz channel-spaced regions
  1225. coming under EUROPE too, have been set as TAVARUA_REGION_US.
  1226. */
  1227. FMDBG("%s: The region selected from APP is"
  1228. " : TAVARUA_REGION_US", __func__);
  1229. break;
  1230. case TAVARUA_REGION_EU:
  1231. /*
  1232. Radio band for all the 50KHz channel-spaced regions
  1233. coming under EUROPE, have been set as TAVARUA_REGION_EU.
  1234. */
  1235. FMDBG("%s: The region selected from APP is : "
  1236. "TAVARUA_REGION_EU", __func__);
  1237. break;
  1238. case TAVARUA_REGION_JAPAN:
  1239. /*
  1240. Radio band for the 100KHz channel-spaced JAPAN region
  1241. has been set as TAVARUA_REGION_JAPAN.
  1242. */
  1243. FMDBG("%s: The region selected from APP is"
  1244. " : TAVARUA_REGION_JAPAN", __func__);
  1245. break;
  1246. case TAVARUA_REGION_JAPAN_WIDE:
  1247. /*
  1248. Radio band for the 50KHz channel-spaced JAPAN WIDE region
  1249. has been set as TAVARUA_REGION_JAPAN_WIDE.
  1250. */
  1251. FMDBG("%s: The region selected from APP is"
  1252. " : TAVARUA_REGION_JAPAN_WIDE", __func__);
  1253. break;
  1254. case TAVARUA_REGION_OTHER:
  1255. /*
  1256. Radio band for all the 100KHz channel-spaced regions
  1257. including those coming under EUROPE have been set as
  1258. TAVARUA_REGION_OTHER.
  1259. */
  1260. FMDBG("%s: The region selected from APP is"
  1261. " : TAVARUA_REGION_OTHER", __func__);
  1262. break;
  1263. default:
  1264. pr_err("%s: Should not reach here.", __func__);
  1265. break;
  1266. }
  1267. /* Enable or Disable the 200KHz enforcer */
  1268. switch (region) {
  1269. case TAVARUA_REGION_US:
  1270. case TAVARUA_REGION_JAPAN:
  1271. case TAVARUA_REGION_OTHER:
  1272. /*
  1273. These are the 3 bands for which we need to enable the
  1274. 200KHz enforcer in ADVCTL reg.
  1275. */
  1276. if (adie_type_bahma) {
  1277. FMDBG("Adie type : Bahama\n");
  1278. FMDBG("%s: Enabling the 200KHz enforcer for"
  1279. " Region : %d", __func__, region);
  1280. /*Enable the 200KHz enforcer*/
  1281. retval = tavarua_read_registers(radio,
  1282. ADVCTRL, 1);
  1283. if (retval >= 0) {
  1284. rdsMask = radio->registers[ADVCTRL];
  1285. SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
  1286. SRCH200KHZ_OFFSET, SRCH_MASK);
  1287. retval = tavarua_write_register(radio,
  1288. ADVCTRL, rdsMask);
  1289. } else
  1290. return retval;
  1291. } /* if Marimba do nothing */
  1292. break;
  1293. case TAVARUA_REGION_EU:
  1294. case TAVARUA_REGION_JAPAN_WIDE:
  1295. /*
  1296. These are the 2 bands for which we need to disable the
  1297. 200KHz enforcer in ADVCTL reg.
  1298. Radio band for all the 50KHz channel-spaced regions
  1299. coming under EUROPE have been set as TAVARUA_REGION_EU.
  1300. */
  1301. if (adie_type_bahma) {
  1302. FMDBG("Adie type : Bahama\n");
  1303. FMDBG("%s: Disabling the 200KHz enforcer for"
  1304. " Region : %d", __func__, region);
  1305. /*
  1306. Disable 200KHz enforcer for all 50 KHz
  1307. spaced regions.
  1308. */
  1309. retval = tavarua_read_registers(radio,
  1310. ADVCTRL, 1);
  1311. if (retval >= 0) {
  1312. rdsMask = radio->registers[ADVCTRL];
  1313. SET_REG_FIELD(rdsMask, NO_SRCH200khz,
  1314. SRCH200KHZ_OFFSET, SRCH_MASK);
  1315. retval = tavarua_write_register(radio,
  1316. ADVCTRL, rdsMask);
  1317. } else
  1318. return retval;
  1319. } /* if Marimba do nothing */
  1320. break;
  1321. default:
  1322. FMDBG("%s: Defaulting in case of Enabling/Disabling"
  1323. "the 200KHz Enforcer", __func__);
  1324. break;
  1325. }
  1326. /* Set channel spacing */
  1327. switch (region) {
  1328. case TAVARUA_REGION_US:
  1329. if ((adie_type_bahma) && (bahama_version == 0x09)) {
  1330. FMDBG("Adie type : Bahama\n");
  1331. /*
  1332. Configuring all 200KHZ spaced regions as 100KHz due to
  1333. change in the new Bahma FM SoC search algorithm.
  1334. */
  1335. value = FM_CH_SPACE_100KHZ;
  1336. } else if ((adie_type_bahma) && (bahama_version == 0x0a)) {
  1337. FMDBG("Adie type : Bahama B1\n");
  1338. value = FM_CH_SPACE_200KHZ;
  1339. } else {
  1340. FMDBG("Adie type : Marimba\n");
  1341. value = FM_CH_SPACE_200KHZ;
  1342. }
  1343. break;
  1344. case TAVARUA_REGION_JAPAN:
  1345. case TAVARUA_REGION_OTHER:
  1346. if ((adie_type_bahma) && (bahama_version == 0x09)) {
  1347. FMDBG("Adie type : Bahama\n");
  1348. FMDBG("%s: Configuring the channel-spacing as 50KHz"
  1349. "for the Region : %d", __func__, region);
  1350. /*
  1351. Configuring all 100KHZ spaced regions as 50KHz due to
  1352. change in the new Bahma FM SoC search algorithm.
  1353. */
  1354. value = FM_CH_SPACE_50KHZ;
  1355. } else if ((adie_type_bahma) && (bahama_version == 0x0a)) {
  1356. FMDBG("Adie type : Bahama B1\n");
  1357. value = FM_CH_SPACE_100KHZ;
  1358. } else {
  1359. FMDBG("Adie type : Marimba\n");
  1360. value = FM_CH_SPACE_100KHZ;
  1361. }
  1362. break;
  1363. case TAVARUA_REGION_EU:
  1364. case TAVARUA_REGION_JAPAN_WIDE:
  1365. value = FM_CH_SPACE_50KHZ;
  1366. break;
  1367. default:
  1368. FMDBG("%s: Defualting in case of Channel-Spacing", __func__);
  1369. break;
  1370. }
  1371. SET_REG_FIELD(radio->registers[RDCTRL], value,
  1372. RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
  1373. return retval;
  1374. }
  1375. /*************************************************************************
  1376. * fops/IOCTL helper functions
  1377. ************************************************************************/
  1378. /*=============================================================================
  1379. FUNCTION: tavarua_search
  1380. =============================================================================*/
  1381. /**
  1382. This interface sets the search control features.
  1383. @param radio: structure pointer passed by client.
  1384. @param on: The value of a control.
  1385. @param dir: FM search direction.
  1386. @return => 0 if successful.
  1387. @return < 0 if failure.
  1388. */
  1389. static int tavarua_search(struct tavarua_device *radio, int on, int dir)
  1390. {
  1391. enum search_t srch;
  1392. FMDBG("In tavarua_search\n");
  1393. if (unlikely(radio == NULL)) {
  1394. FMDERR("%s:radio is null", __func__);
  1395. return -EINVAL;
  1396. }
  1397. srch = radio->registers[SRCHCTRL] & SRCH_MODE;
  1398. if (on) {
  1399. radio->registers[SRCHRDS1] = 0x00;
  1400. radio->registers[SRCHRDS2] = 0x00;
  1401. /* Set freq band */
  1402. switch (srch) {
  1403. case SCAN_FOR_STRONG:
  1404. case SCAN_FOR_WEAK:
  1405. radio->srch_params.get_list = 1;
  1406. radio->registers[SRCHRDS2] =
  1407. radio->srch_params.preset_num;
  1408. break;
  1409. case RDS_SEEK_PTY:
  1410. case RDS_SCAN_PTY:
  1411. radio->registers[SRCHRDS2] =
  1412. radio->srch_params.srch_pty;
  1413. break;
  1414. case RDS_SEEK_PI:
  1415. radio->registers[SRCHRDS1] =
  1416. (radio->srch_params.srch_pi & 0xFF00) >> 8;
  1417. radio->registers[SRCHRDS2] =
  1418. (radio->srch_params.srch_pi & 0x00FF);
  1419. break;
  1420. default:
  1421. break;
  1422. }
  1423. radio->registers[SRCHCTRL] |= SRCH_ON;
  1424. } else {
  1425. radio->registers[SRCHCTRL] &= ~SRCH_ON;
  1426. radio->srch_params.get_list = 0;
  1427. }
  1428. radio->registers[SRCHCTRL] = (dir << 3) |
  1429. (radio->registers[SRCHCTRL] & 0xF7);
  1430. FMDBG("SRCHCTRL <%x>\n", radio->registers[SRCHCTRL]);
  1431. FMDBG("Search Started\n");
  1432. return tavarua_write_registers(radio, SRCHRDS1,
  1433. &radio->registers[SRCHRDS1], 3);
  1434. }
  1435. /*=============================================================================
  1436. FUNCTION: tavarua_set_region
  1437. =============================================================================*/
  1438. /**
  1439. This interface configures the FM radio.
  1440. @param radio: structure pointer passed by client.
  1441. @param req_region: FM band types. These types defines the FM band minimum and
  1442. maximum frequencies in the FM band.
  1443. @return => 0 if successful.
  1444. @return < 0 if failure.
  1445. */
  1446. static int tavarua_set_region(struct tavarua_device *radio,
  1447. int req_region)
  1448. {
  1449. int retval = 0;
  1450. unsigned int rdsMask = 0;
  1451. unsigned char xfr_buf[XFR_REG_NUM];
  1452. unsigned char value;
  1453. unsigned int spacing = 0.100 * FREQ_MUL;
  1454. unsigned int band_low, band_high;
  1455. unsigned int low_band_limit = 76.0 * FREQ_MUL;
  1456. enum tavarua_region_t region = req_region;
  1457. unsigned char adie_type_bahma;
  1458. if (unlikely(radio == NULL)) {
  1459. FMDERR("%s:radio is null", __func__);
  1460. return -EINVAL;
  1461. }
  1462. adie_type_bahma = is_bahama();
  1463. /* Set freq band */
  1464. if (region == TAVARUA_REGION_JAPAN)
  1465. SET_REG_FIELD(radio->registers[RDCTRL], 1,
  1466. RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
  1467. else
  1468. SET_REG_FIELD(radio->registers[RDCTRL], 0,
  1469. RDCTRL_BAND_OFFSET, RDCTRL_BAND_MASK);
  1470. /* Set De-emphasis and soft band range*/
  1471. SET_REG_FIELD(radio->registers[RDCTRL], radio->region_params.emphasis,
  1472. RDCTRL_DEEMPHASIS_OFFSET, RDCTRL_DEEMPHASIS_MASK);
  1473. /* set RDS standard */
  1474. SET_REG_FIELD(radio->registers[RDSCTRL], radio->region_params.rds_std,
  1475. RDSCTRL_STANDARD_OFFSET, RDSCTRL_STANDARD_MASK);
  1476. FMDBG("RDSCTRLL %x\n", radio->registers[RDSCTRL]);
  1477. retval = tavarua_write_register(radio, RDSCTRL,
  1478. radio->registers[RDSCTRL]);
  1479. if (retval < 0) {
  1480. FMDERR("Failed to set RDS/RBDS standard\n");
  1481. return retval;
  1482. }
  1483. /* Set the lower and upper band limits*/
  1484. retval = sync_read_xfr(radio, RADIO_CONFIG, xfr_buf);
  1485. if (retval < 0) {
  1486. FMDERR("failed to get RADIO_CONFIG\n");
  1487. return retval;
  1488. }
  1489. band_low = (radio->region_params.band_low -
  1490. low_band_limit) / spacing;
  1491. band_high = (radio->region_params.band_high -
  1492. low_band_limit) / spacing;
  1493. xfr_buf[0] = RSH_DATA(band_low, 8);
  1494. xfr_buf[1] = GET_ABS_VAL(band_low);
  1495. xfr_buf[2] = RSH_DATA(band_high, 8);
  1496. xfr_buf[3] = GET_ABS_VAL(band_high);
  1497. xfr_buf[4] = 0; /* Active LOW */
  1498. retval = sync_write_xfr(radio, RADIO_CONFIG, xfr_buf);
  1499. if (retval < 0) {
  1500. FMDERR("Could not set regional settings\n");
  1501. return retval;
  1502. }
  1503. radio->region_params.region = region;
  1504. /* Check for the FM Algorithm used */
  1505. if (radio->enable_optimized_srch_alg) {
  1506. FMDBG("Optimized Srch Algorithm!!!");
  1507. optimized_search_algorithm(radio, region);
  1508. } else {
  1509. FMDBG("Native Srch Algorithm!!!");
  1510. /* Enable/Disable the 200KHz enforcer */
  1511. switch (region) {
  1512. case TAVARUA_REGION_US:
  1513. if (adie_type_bahma) {
  1514. FMDBG("Adie type : Bahama\n");
  1515. /*Enable the 200KHz enforcer*/
  1516. retval = tavarua_read_registers(radio,
  1517. ADVCTRL, 1);
  1518. if (retval >= 0) {
  1519. rdsMask = radio->registers[ADVCTRL];
  1520. SET_REG_FIELD(rdsMask, ENF_SRCH200khz,
  1521. SRCH200KHZ_OFFSET, SRCH_MASK);
  1522. retval = tavarua_write_register(radio,
  1523. ADVCTRL, rdsMask);
  1524. } else
  1525. return retval;
  1526. } /* if Marimba do nothing */
  1527. break;
  1528. case TAVARUA_REGION_EU:
  1529. case TAVARUA_REGION_JAPAN:
  1530. case TAVARUA_REGION_JAPAN_WIDE:
  1531. default:
  1532. if (adie_type_bahma) {
  1533. FMDBG("Adie type : Bahama\n");
  1534. /*
  1535. Disable 200KHz enforcer for all 100/50 KHz
  1536. spaced regions.
  1537. */
  1538. retval = tavarua_read_registers(radio,
  1539. ADVCTRL, 1);
  1540. if (retval >= 0) {
  1541. rdsMask = radio->registers[ADVCTRL];
  1542. SET_REG_FIELD(rdsMask, NO_SRCH200khz,
  1543. SRCH200KHZ_OFFSET, SRCH_MASK);
  1544. retval = tavarua_write_register(radio,
  1545. ADVCTRL, rdsMask);
  1546. } else
  1547. return retval;
  1548. } /* if Marimba do nothing */
  1549. break;
  1550. }
  1551. /* Set channel spacing */
  1552. if (region == TAVARUA_REGION_US) {
  1553. if (adie_type_bahma) {
  1554. FMDBG("Adie type : Bahama\n");
  1555. /*
  1556. Configuring all 200KHZ spaced regions as
  1557. 100KHz due to change in the new Bahma
  1558. FM SoC search algorithm.
  1559. */
  1560. value = FM_CH_SPACE_100KHZ;
  1561. } else {
  1562. FMDBG("Adie type : Marimba\n");
  1563. value = FM_CH_SPACE_200KHZ;
  1564. }
  1565. } else {
  1566. /*
  1567. Set the channel spacing as configured from
  1568. the upper layers.
  1569. */
  1570. value = radio->region_params.spacing;
  1571. }
  1572. SET_REG_FIELD(radio->registers[RDCTRL], value,
  1573. RDCTRL_CHSPACE_OFFSET, RDCTRL_CHSPACE_MASK);
  1574. }
  1575. /* Write the config values into RDCTL register */
  1576. FMDBG("RDCTRL: %x\n", radio->registers[RDCTRL]);
  1577. retval = tavarua_write_register(radio, RDCTRL,
  1578. radio->registers[RDCTRL]);
  1579. if (retval < 0) {
  1580. FMDERR("Could not set region in rdctrl\n");
  1581. return retval;
  1582. }
  1583. return retval;
  1584. }
  1585. /*=============================================================================
  1586. FUNCTION: tavarua_get_freq
  1587. =============================================================================*/
  1588. /**
  1589. This interface gets the current frequency.
  1590. @param radio: structure pointer passed by client.
  1591. @param freq: struct v4l2_frequency. This will be set to the resultant
  1592. frequency in units of 62.5 kHz on success.
  1593. NOTE:
  1594. To get the current tuner or modulator radio frequency applications set the
  1595. tuner field of a struct v4l2_frequency to the respective tuner or modulator
  1596. number (only input devices have tuners, only output devices have modulators),
  1597. zero out the reserved array and call the VIDIOC_G_FREQUENCY ioctl with a
  1598. pointer to this structure. The driver stores the current frequency in the
  1599. frequency field.
  1600. Tuning frequency is in units of 62.5 kHz, or if the struct v4l2_tuner or
  1601. struct v4l2_modulator capabilities flag V4L2_TUNER_CAP_LOW is set, in
  1602. units of 62.5 Hz.
  1603. @return => 0 if successful.
  1604. @return < 0 if failure.
  1605. */
  1606. static int tavarua_get_freq(struct tavarua_device *radio,
  1607. struct v4l2_frequency *freq)
  1608. {
  1609. int retval;
  1610. unsigned short chan;
  1611. unsigned int band_bottom;
  1612. unsigned int spacing;
  1613. if (unlikely(radio == NULL)) {
  1614. FMDERR("%s:radio is null", __func__);
  1615. return -EINVAL;
  1616. }
  1617. if (unlikely(freq == NULL)) {
  1618. FMDERR("%s:freq is null", __func__);
  1619. return -EINVAL;
  1620. }
  1621. band_bottom = radio->region_params.band_low;
  1622. spacing = 0.100 * FREQ_MUL;
  1623. /* read channel */
  1624. retval = tavarua_read_registers(radio, FREQ, 2);
  1625. chan = radio->registers[FREQ];
  1626. /* Frequency (MHz) = 100 (kHz) x Channel + Bottom of Band (MHz) */
  1627. freq->frequency = spacing * chan + band_bottom;
  1628. if (radio->registers[TUNECTRL] & ADD_OFFSET)
  1629. freq->frequency += 800;
  1630. return retval;
  1631. }
  1632. /*=============================================================================
  1633. FUNCTION: tavarua_set_freq
  1634. =============================================================================*/
  1635. /**
  1636. This interface sets the current frequency.
  1637. @param radio: structure pointer passed by client.
  1638. @param freq: desired frequency sent by the client in 62.5 kHz units.
  1639. NOTE:
  1640. To change the current tuner or modulator radio frequency, applications
  1641. initialize the tuner, type and frequency fields, and the reserved array of a
  1642. struct v4l2_frequency and call the VIDIOC_S_FREQUENCY ioctl with a pointer to
  1643. this structure. When the requested frequency is not possible the driver
  1644. assumes the closest possible value. However VIDIOC_S_FREQUENCY is a
  1645. write-only ioctl, it does not return the actual new frequency.
  1646. Tuning frequency is in units of 62.5 kHz, or if the struct v4l2_tuner
  1647. or struct v4l2_modulator capabilities flag V4L2_TUNER_CAP_LOW is set,
  1648. in units of 62.5 Hz.
  1649. @return => 0 if successful.
  1650. @return < 0 if failure.
  1651. */
  1652. static int tavarua_set_freq(struct tavarua_device *radio, unsigned int freq)
  1653. {
  1654. unsigned int band_bottom;
  1655. unsigned char chan;
  1656. unsigned char cmd[] = {0x00, 0x00};
  1657. unsigned int spacing;
  1658. int retval;
  1659. if (unlikely(radio == NULL)) {
  1660. FMDERR("%s:radio is null", __func__);
  1661. return -EINVAL;
  1662. }
  1663. band_bottom = radio->region_params.band_low;
  1664. spacing = 0.100 * FREQ_MUL;
  1665. if ((freq % 1600) == 800) {
  1666. cmd[1] = ADD_OFFSET;
  1667. freq -= 800;
  1668. }
  1669. /* Chan = [ Freq (Mhz) - Bottom of Band (MHz) ] / 100 (kHz) */
  1670. chan = (freq - band_bottom) / spacing;
  1671. cmd[0] = chan;
  1672. cmd[1] |= TUNE_STATION;
  1673. radio->tune_req = 1;
  1674. retval = tavarua_write_registers(radio, FREQ, cmd, 2);
  1675. if (retval < 0)
  1676. radio->tune_req = 0;
  1677. return retval;
  1678. }
  1679. /**************************************************************************
  1680. * File Operations Interface
  1681. *************************************************************************/
  1682. /*=============================================================================
  1683. FUNCTION: tavarua_fops_read
  1684. =============================================================================*/
  1685. /**
  1686. This function is called when a process, which already opened the dev file,
  1687. attempts to read from it.
  1688. In case of tavarua driver, it is called to read RDS data.
  1689. @param file: file descriptor.
  1690. @param buf: The buffer to fill with data.
  1691. @param count: The length of the buffer in bytes.
  1692. @param ppos: Our offset in the file.
  1693. @return The number of bytes put into the buffer on sucess.
  1694. -EFAULT if there is no access to user buffer
  1695. */
  1696. static ssize_t tavarua_fops_read(struct file *file, char __user *buf,
  1697. size_t count, loff_t *ppos)
  1698. {
  1699. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  1700. struct kfifo *rds_buf;
  1701. if (unlikely(radio == NULL)) {
  1702. FMDERR("%s:radio is null", __func__);
  1703. return -EINVAL;
  1704. }
  1705. if (unlikely(buf == NULL)) {
  1706. FMDERR("%s:buf is null", __func__);
  1707. return -EINVAL;
  1708. }
  1709. rds_buf = &radio->data_buf[TAVARUA_BUF_RAW_RDS];
  1710. /* block if no new data available */
  1711. while (!kfifo_len(rds_buf)) {
  1712. if (file->f_flags & O_NONBLOCK)
  1713. return -EWOULDBLOCK;
  1714. if (wait_event_interruptible(radio->read_queue,
  1715. kfifo_len(rds_buf)) < 0)
  1716. return -EINTR;
  1717. }
  1718. /* calculate block count from byte count */
  1719. count /= BYTES_PER_BLOCK;
  1720. /* check if we can write to the user buffer */
  1721. if (!access_ok(VERIFY_WRITE, buf, count*BYTES_PER_BLOCK))
  1722. return -EFAULT;
  1723. /* copy RDS block out of internal buffer and to user buffer */
  1724. return kfifo_out_locked(rds_buf, buf, count*BYTES_PER_BLOCK,
  1725. &radio->buf_lock[TAVARUA_BUF_RAW_RDS]);
  1726. }
  1727. /*=============================================================================
  1728. FUNCTION: tavarua_fops_write
  1729. =============================================================================*/
  1730. /**
  1731. This function is called when a process, which already opened the dev file,
  1732. attempts to write to it.
  1733. In case of tavarua driver, it is called to write RDS data to host.
  1734. @param file: file descriptor.
  1735. @param buf: The buffer which has data to write.
  1736. @param count: The length of the buffer.
  1737. @param ppos: Our offset in the file.
  1738. @return The number of bytes written from the buffer.
  1739. */
  1740. static ssize_t tavarua_fops_write(struct file *file, const char __user *data,
  1741. size_t count, loff_t *ppos)
  1742. {
  1743. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  1744. int retval = 0;
  1745. int bytes_to_copy;
  1746. int bytes_copied = 0;
  1747. int bytes_left;
  1748. int chunk_index = 0;
  1749. unsigned char tx_data[XFR_REG_NUM];
  1750. if (unlikely(radio == NULL)) {
  1751. FMDERR("%s:radio is null", __func__);
  1752. return -EINVAL;
  1753. }
  1754. if (unlikely(data == NULL)) {
  1755. FMDERR("%s:data is null", __func__);
  1756. return -EINVAL;
  1757. }
  1758. /* Disable TX of this type first */
  1759. switch (radio->tx_mode) {
  1760. case TAVARUA_TX_RT:
  1761. bytes_left = min((int)count, MAX_RT_LENGTH);
  1762. tx_data[1] = 0;
  1763. break;
  1764. case TAVARUA_TX_PS:
  1765. bytes_left = min((int)count, MAX_PS_LENGTH);
  1766. tx_data[4] = 0;
  1767. break;
  1768. default:
  1769. FMDERR("%s: Unknown TX mode\n", __func__);
  1770. return -1;
  1771. }
  1772. retval = sync_write_xfr(radio, radio->tx_mode, tx_data);
  1773. if (retval < 0)
  1774. return retval;
  1775. /* send payload to FM hardware */
  1776. while (bytes_left) {
  1777. chunk_index++;
  1778. bytes_to_copy = min(bytes_left, XFR_REG_NUM);
  1779. if (copy_from_user(tx_data, data + bytes_copied, bytes_to_copy))
  1780. return -EFAULT;
  1781. retval = sync_write_xfr(radio, radio->tx_mode +
  1782. chunk_index, tx_data);
  1783. if (retval < 0)
  1784. return retval;
  1785. bytes_copied += bytes_to_copy;
  1786. bytes_left -= bytes_to_copy;
  1787. }
  1788. /* send the header */
  1789. switch (radio->tx_mode) {
  1790. case TAVARUA_TX_RT:
  1791. FMDBG("Writing RT header\n");
  1792. tx_data[0] = bytes_copied;
  1793. tx_data[1] = TX_ON | 0x03; /* on | PTY */
  1794. tx_data[2] = 0x12; /* PI high */
  1795. tx_data[3] = 0x34; /* PI low */
  1796. break;
  1797. case TAVARUA_TX_PS:
  1798. FMDBG("Writing PS header\n");
  1799. tx_data[0] = chunk_index;
  1800. tx_data[1] = 0x03; /* PTY */
  1801. tx_data[2] = 0x12; /* PI high */
  1802. tx_data[3] = 0x34; /* PI low */
  1803. tx_data[4] = TX_ON | 0x01;
  1804. break;
  1805. default:
  1806. FMDERR("%s: Unknown TX mode\n", __func__);
  1807. return -1;
  1808. }
  1809. retval = sync_write_xfr(radio, radio->tx_mode, tx_data);
  1810. if (retval < 0)
  1811. return retval;
  1812. FMDBG("done writing: %d\n", retval);
  1813. return bytes_copied;
  1814. }
  1815. /*=============================================================================
  1816. FUNCTION: tavarua_fops_open
  1817. =============================================================================*/
  1818. /**
  1819. This function is called when a process tries to open the device file, like
  1820. "cat /dev/mycharfile"
  1821. @param file: file descriptor.
  1822. @return => 0 if successful.
  1823. @return < 0 if failure.
  1824. */
  1825. static int tavarua_fops_open(struct file *file)
  1826. {
  1827. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  1828. struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
  1829. int retval = -ENODEV;
  1830. unsigned char value;
  1831. /* FM core bring up */
  1832. int i = 0;
  1833. char fm_ctl0_part1[] = { 0xCA, 0xCE, 0xD6 };
  1834. char fm_ctl1[] = { 0x03 };
  1835. char fm_ctl0_part2[] = { 0xB6, 0xB7 };
  1836. char buffer[] = {0x00, 0x48, 0x8A, 0x8E, 0x97, 0xB7};
  1837. int bahama_present = -ENODEV;
  1838. if (unlikely(radio == NULL)) {
  1839. FMDERR("%s:radio is null", __func__);
  1840. return -EINVAL;
  1841. }
  1842. INIT_DELAYED_WORK(&radio->work, read_int_stat);
  1843. if (!atomic_dec_and_test(&radio->users)) {
  1844. pr_err("%s: Device already in use."
  1845. "Try again later", __func__);
  1846. atomic_inc(&radio->users);
  1847. return -EBUSY;
  1848. }
  1849. /* initial gpio pin config & Power up */
  1850. retval = radio->pdata->fm_setup(radio->pdata);
  1851. if (retval) {
  1852. printk(KERN_ERR "%s: failed config gpio & pmic\n", __func__);
  1853. goto open_err_setup;
  1854. }
  1855. if (radio->pdata->config_i2s_gpio != NULL) {
  1856. retval = radio->pdata->config_i2s_gpio(FM_I2S_ON);
  1857. if (retval) {
  1858. printk(KERN_ERR "%s: failed config gpio\n", __func__);
  1859. goto config_i2s_err;
  1860. }
  1861. }
  1862. /* enable irq */
  1863. retval = tavarua_request_irq(radio);
  1864. if (retval < 0) {
  1865. printk(KERN_ERR "%s: failed to request irq\n", __func__);
  1866. goto open_err_req_irq;
  1867. }
  1868. /* call top level marimba interface here to enable FM core */
  1869. FMDBG("initializing SoC\n");
  1870. bahama_present = is_bahama();
  1871. if (bahama_present == -ENODEV)
  1872. return -ENODEV;
  1873. marimba_set_fm_status(radio->marimba, true);
  1874. if (bahama_present)
  1875. radio->marimba->mod_id = SLAVE_ID_BAHAMA;
  1876. else
  1877. radio->marimba->mod_id = MARIMBA_SLAVE_ID_MARIMBA;
  1878. value = FM_ENABLE;
  1879. retval = marimba_write_bit_mask(&config,
  1880. MARIMBA_XO_BUFF_CNTRL, &value, 1, value);
  1881. if (retval < 0) {
  1882. printk(KERN_ERR "%s:XO_BUFF_CNTRL write failed\n",
  1883. __func__);
  1884. goto open_err_all;
  1885. }
  1886. /* Bring up FM core */
  1887. if (bahama_present) {
  1888. radio->marimba->mod_id = SLAVE_ID_BAHAMA;
  1889. /* Read the Bahama version*/
  1890. retval = marimba_read_bit_mask(&config,
  1891. 0x00, &bahama_version, 1, 0x1F);
  1892. if (retval < 0) {
  1893. printk(KERN_ERR "%s: version read failed",
  1894. __func__);
  1895. goto open_err_all;
  1896. }
  1897. /* Check for Bahama V2 variant*/
  1898. if ((bahama_version == 0x09) || (bahama_version == 0x0a)) {
  1899. /* In case of Bahama v2, forcefully enable the
  1900. * internal analog and digital voltage controllers
  1901. */
  1902. value = 0x06;
  1903. /* value itself used as mask in these writes*/
  1904. retval = marimba_write_bit_mask(&config,
  1905. BAHAMA_LDO_DREG_CTL0, &value, 1, value);
  1906. if (retval < 0) {
  1907. printk(KERN_ERR "%s:0xF0 write failed\n",
  1908. __func__);
  1909. goto open_err_all;
  1910. }
  1911. value = 0x86;
  1912. retval = marimba_write_bit_mask(&config,
  1913. BAHAMA_LDO_AREG_CTL0, &value, 1, value);
  1914. if (retval < 0) {
  1915. printk(KERN_ERR "%s:0xF4 write failed\n",
  1916. __func__);
  1917. goto open_err_all;
  1918. }
  1919. }
  1920. /*write FM mode*/
  1921. retval = tavarua_write_register(radio, BAHAMA_FM_MODE_REG,
  1922. BAHAMA_FM_MODE_NORMAL);
  1923. if (retval < 0) {
  1924. printk(KERN_ERR "failed to set the FM mode: %d\n",
  1925. retval);
  1926. goto open_err_all;
  1927. }
  1928. /*Write first sequence of bytes to FM_CTL0*/
  1929. for (i = 0; i < 3; i++) {
  1930. retval = tavarua_write_register(radio,
  1931. BAHAMA_FM_CTL0_REG, fm_ctl0_part1[i]);
  1932. if (retval < 0) {
  1933. printk(KERN_ERR "FM_CTL0:set-1 failure: %d\n",
  1934. retval);
  1935. goto open_err_all;
  1936. }
  1937. }
  1938. /*Write the FM_CTL1 sequence*/
  1939. for (i = 0; i < 1; i++) {
  1940. retval = tavarua_write_register(radio,
  1941. BAHAMA_FM_CTL1_REG, fm_ctl1[i]);
  1942. if (retval < 0) {
  1943. printk(KERN_ERR "FM_CTL1 write failure: %d\n",
  1944. retval);
  1945. goto open_err_all;
  1946. }
  1947. }
  1948. /*Write second sequence of bytes to FM_CTL0*/
  1949. for (i = 0; i < 2; i++) {
  1950. retval = tavarua_write_register(radio,
  1951. BAHAMA_FM_CTL0_REG, fm_ctl0_part2[i]);
  1952. if (retval < 0) {
  1953. printk(KERN_ERR "FM_CTL0:set-2 failure: %d\n",
  1954. retval);
  1955. goto open_err_all;
  1956. }
  1957. }
  1958. } else {
  1959. retval = tavarua_write_registers(radio, LEAKAGE_CNTRL,
  1960. buffer, 6);
  1961. if (retval < 0) {
  1962. printk(KERN_ERR "%s: failed to bring up FM Core\n",
  1963. __func__);
  1964. goto open_err_all;
  1965. }
  1966. }
  1967. /* Wait for interrupt i.e. complete(&radio->sync_req_done); call */
  1968. /*Initialize the completion variable for
  1969. for the proper behavior*/
  1970. init_completion(&radio->sync_req_done);
  1971. if (!wait_for_completion_timeout(&radio->sync_req_done,
  1972. msecs_to_jiffies(wait_timeout))) {
  1973. retval = -1;
  1974. FMDERR("Timeout waiting for initialization\n");
  1975. }
  1976. /* get Chip ID */
  1977. retval = tavarua_write_register(radio, XFRCTRL, CHIPID);
  1978. if (retval < 0)
  1979. goto open_err_all;
  1980. msleep(TAVARUA_DELAY);
  1981. tavarua_read_registers(radio, XFRCTRL, XFR_REG_NUM+1);
  1982. if (radio->registers[XFRCTRL] != CHIPID)
  1983. goto open_err_all;
  1984. radio->chipID = (radio->registers[XFRCTRL+2] << 24) |
  1985. (radio->registers[XFRCTRL+5] << 16) |
  1986. (radio->registers[XFRCTRL+6] << 8) |
  1987. (radio->registers[XFRCTRL+7]);
  1988. printk(KERN_WARNING DRIVER_NAME ": Chip ID %x\n", radio->chipID);
  1989. if (radio->chipID == MARIMBA_A0) {
  1990. printk(KERN_WARNING DRIVER_NAME ": Unsupported hardware: %x\n",
  1991. radio->chipID);
  1992. retval = -1;
  1993. goto open_err_all;
  1994. }
  1995. radio->handle_irq = 0;
  1996. radio->marimba->mod_id = SLAVE_ID_BAHAMA;
  1997. return 0;
  1998. open_err_all:
  1999. /*Disable FM in case of error*/
  2000. value = 0x00;
  2001. marimba_write_bit_mask(&config, MARIMBA_XO_BUFF_CNTRL,
  2002. &value, 1, value);
  2003. tavarua_disable_irq(radio);
  2004. open_err_req_irq:
  2005. if (radio->pdata->config_i2s_gpio != NULL)
  2006. radio->pdata->config_i2s_gpio(FM_I2S_OFF);
  2007. config_i2s_err:
  2008. radio->pdata->fm_shutdown(radio->pdata);
  2009. open_err_setup:
  2010. marimba_set_fm_status(radio->marimba, false);
  2011. radio->handle_irq = 1;
  2012. atomic_inc(&radio->users);
  2013. return retval;
  2014. }
  2015. /*=============================================================================
  2016. FUNCTION: tavarua_fops_release
  2017. =============================================================================*/
  2018. /**
  2019. This function is called when a process closes the device file.
  2020. @param file: file descriptor.
  2021. @return => 0 if successful.
  2022. @return < 0 if failure.
  2023. */
  2024. static int tavarua_fops_release(struct file *file)
  2025. {
  2026. int retval;
  2027. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  2028. struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
  2029. unsigned char value;
  2030. int i = 0;
  2031. /*FM Core shutdown sequence for Bahama*/
  2032. char fm_ctl0_part1[] = { 0xB7 };
  2033. char fm_ctl1[] = { 0x03 };
  2034. char fm_ctl0_part2[] = { 0x9F, 0x48, 0x02 };
  2035. int bahama_present = -ENODEV;
  2036. /*FM Core shutdown sequence for Marimba*/
  2037. char buffer[] = {0x18, 0xB7, 0x48};
  2038. bool bt_status = false;
  2039. int index;
  2040. /* internal regulator controllers DREG_CTL0, AREG_CTL0
  2041. * has to be kept in the valid state based on the bt status.
  2042. * 1st row is the state when no clients are active,
  2043. * and the second when bt is in on state.
  2044. */
  2045. char internal_vreg_ctl[2][2] = {
  2046. { 0x04, 0x84 },
  2047. { 0x00, 0x80 }
  2048. };
  2049. if (!radio) {
  2050. pr_err("%s: Radio device not available...", __func__);
  2051. return -ENODEV;
  2052. }
  2053. FMDBG("In %s", __func__);
  2054. FMDBG("%s, Disabling the IRQs\n", __func__);
  2055. /* disable irq */
  2056. retval = tavarua_disable_irq(radio);
  2057. if (retval < 0) {
  2058. printk(KERN_ERR "%s: failed to disable irq\n", __func__);
  2059. return retval;
  2060. }
  2061. /* disable radio ctrl */
  2062. retval = tavarua_write_register(radio, RDCTRL, 0x00);
  2063. if (retval < 0) {
  2064. printk(KERN_ERR "%s: failed to disable FM\n", __func__);
  2065. return retval;
  2066. }
  2067. init_completion(&radio->shutdown_done);
  2068. bahama_present = is_bahama();
  2069. if (bahama_present == -ENODEV)
  2070. return -ENODEV;
  2071. INIT_DELAYED_WORK(&radio->work, fm_shutdown);
  2072. if (bahama_present) {
  2073. /*Write first sequence of bytes to FM_CTL0*/
  2074. for (i = 0; i < 1; i++) {
  2075. retval = tavarua_write_register(radio,
  2076. BAHAMA_FM_CTL0_REG, fm_ctl0_part1[i]);
  2077. if (retval < 0) {
  2078. printk(KERN_ERR "FM_CTL0:Set-1 failure: %d\n",
  2079. retval);
  2080. break;
  2081. }
  2082. }
  2083. /*Write the FM_CTL1 sequence*/
  2084. for (i = 0; i < 1; i++) {
  2085. retval = tavarua_write_register(radio,
  2086. BAHAMA_FM_CTL1_REG, fm_ctl1[i]);
  2087. if (retval < 0) {
  2088. printk(KERN_ERR "FM_CTL1 failure: %d\n",
  2089. retval);
  2090. break;
  2091. }
  2092. }
  2093. /*Write second sequence of bytes to FM_CTL0*/
  2094. for (i = 0; i < 3; i++) {
  2095. retval = tavarua_write_register(radio,
  2096. BAHAMA_FM_CTL0_REG, fm_ctl0_part2[i]);
  2097. if (retval < 0) {
  2098. printk(KERN_ERR "FM_CTL0:Set-2 failure: %d\n",
  2099. retval);
  2100. break;
  2101. }
  2102. }
  2103. } else {
  2104. retval = tavarua_write_registers(radio, FM_CTL0,
  2105. buffer, sizeof(buffer)/sizeof(buffer[0]));
  2106. if (retval < 0) {
  2107. printk(KERN_ERR "%s: failed to bring down the FM Core\n",
  2108. __func__);
  2109. return retval;
  2110. }
  2111. }
  2112. radio->marimba->mod_id = SLAVE_ID_BAHAMA;
  2113. bt_status = marimba_get_bt_status(radio->marimba);
  2114. /* Set the index based on the bt status*/
  2115. index = bt_status ? 1 : 0;
  2116. /* Check for Bahama's existance and Bahama V2 variant*/
  2117. if (bahama_present
  2118. && (bahama_version == 0x09 || bahama_version == 0x0a)) {
  2119. radio->marimba->mod_id = SLAVE_ID_BAHAMA;
  2120. /* actual value itself used as mask*/
  2121. retval = marimba_write_bit_mask(&config,
  2122. BAHAMA_LDO_DREG_CTL0, &internal_vreg_ctl[bt_status][0],
  2123. 1, internal_vreg_ctl[index][0]);
  2124. if (retval < 0) {
  2125. printk(KERN_ERR "%s:0xF0 write failed\n", __func__);
  2126. goto exit;
  2127. }
  2128. /* actual value itself used as mask*/
  2129. retval = marimba_write_bit_mask(&config,
  2130. BAHAMA_LDO_AREG_CTL0, &internal_vreg_ctl[bt_status][1],
  2131. 1, internal_vreg_ctl[index][1]);
  2132. if (retval < 0) {
  2133. printk(KERN_ERR "%s:0xF4 write failed\n", __func__);
  2134. goto exit;
  2135. }
  2136. } else {
  2137. /* disable fm core */
  2138. radio->marimba->mod_id = MARIMBA_SLAVE_ID_MARIMBA;
  2139. }
  2140. value = 0x00;
  2141. retval = marimba_write_bit_mask(&config, MARIMBA_XO_BUFF_CNTRL,
  2142. &value, 1, FM_ENABLE);
  2143. if (retval < 0) {
  2144. printk(KERN_ERR "%s:XO_BUFF_CNTRL write failed\n", __func__);
  2145. goto exit;
  2146. }
  2147. exit:
  2148. FMDBG("%s, Calling fm_shutdown\n", __func__);
  2149. queue_delayed_work(radio->wqueue, &radio->work,
  2150. msecs_to_jiffies(TAVARUA_DELAY/2));
  2151. /* teardown gpio and pmic */
  2152. marimba_set_fm_status(radio->marimba, false);
  2153. wait_for_completion(&radio->shutdown_done);
  2154. radio->handle_irq = 1;
  2155. radio->lp_mode = 1;
  2156. radio->spur_table_size = 0;
  2157. atomic_inc(&radio->users);
  2158. radio->marimba->mod_id = SLAVE_ID_BAHAMA;
  2159. flush_workqueue(radio->wqueue);
  2160. return retval;
  2161. }
  2162. /*
  2163. * tavarua_fops - file operations interface
  2164. */
  2165. static const struct v4l2_file_operations tavarua_fops = {
  2166. .owner = THIS_MODULE,
  2167. .read = tavarua_fops_read,
  2168. .write = tavarua_fops_write,
  2169. .ioctl = video_ioctl2,
  2170. .open = tavarua_fops_open,
  2171. .release = tavarua_fops_release,
  2172. };
  2173. /*************************************************************************
  2174. * Video4Linux Interface
  2175. *************************************************************************/
  2176. /*
  2177. * tavarua_v4l2_queryctrl - query control
  2178. */
  2179. static struct v4l2_queryctrl tavarua_v4l2_queryctrl[] = {
  2180. {
  2181. .id = V4L2_CID_AUDIO_VOLUME,
  2182. .type = V4L2_CTRL_TYPE_INTEGER,
  2183. .name = "Volume",
  2184. .minimum = 0,
  2185. .maximum = 15,
  2186. .step = 1,
  2187. .default_value = 15,
  2188. },
  2189. {
  2190. .id = V4L2_CID_AUDIO_BALANCE,
  2191. .flags = V4L2_CTRL_FLAG_DISABLED,
  2192. },
  2193. {
  2194. .id = V4L2_CID_AUDIO_BASS,
  2195. .flags = V4L2_CTRL_FLAG_DISABLED,
  2196. },
  2197. {
  2198. .id = V4L2_CID_AUDIO_TREBLE,
  2199. .flags = V4L2_CTRL_FLAG_DISABLED,
  2200. },
  2201. {
  2202. .id = V4L2_CID_AUDIO_MUTE,
  2203. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2204. .name = "Mute",
  2205. .minimum = 0,
  2206. .maximum = 1,
  2207. .step = 1,
  2208. .default_value = 1,
  2209. },
  2210. {
  2211. .id = V4L2_CID_AUDIO_LOUDNESS,
  2212. .flags = V4L2_CTRL_FLAG_DISABLED,
  2213. },
  2214. {
  2215. .id = V4L2_CID_PRIVATE_TAVARUA_SRCHMODE,
  2216. .type = V4L2_CTRL_TYPE_INTEGER,
  2217. .name = "Search mode",
  2218. .minimum = 0,
  2219. .maximum = 7,
  2220. .step = 1,
  2221. .default_value = 0,
  2222. },
  2223. {
  2224. .id = V4L2_CID_PRIVATE_TAVARUA_SCANDWELL,
  2225. .type = V4L2_CTRL_TYPE_INTEGER,
  2226. .name = "Search dwell time",
  2227. .minimum = 0,
  2228. .maximum = 7,
  2229. .step = 1,
  2230. .default_value = 0,
  2231. },
  2232. {
  2233. .id = V4L2_CID_PRIVATE_TAVARUA_SRCHON,
  2234. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2235. .name = "Search on/off",
  2236. .minimum = 0,
  2237. .maximum = 1,
  2238. .step = 1,
  2239. .default_value = 1,
  2240. },
  2241. {
  2242. .id = V4L2_CID_PRIVATE_TAVARUA_STATE,
  2243. .type = V4L2_CTRL_TYPE_INTEGER,
  2244. .name = "radio 0ff/rx/tx/reset",
  2245. .minimum = 0,
  2246. .maximum = 3,
  2247. .step = 1,
  2248. .default_value = 1,
  2249. },
  2250. {
  2251. .id = V4L2_CID_PRIVATE_TAVARUA_REGION,
  2252. .type = V4L2_CTRL_TYPE_INTEGER,
  2253. .name = "radio standard",
  2254. .minimum = 0,
  2255. .maximum = 2,
  2256. .step = 1,
  2257. .default_value = 0,
  2258. },
  2259. {
  2260. .id = V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH,
  2261. .type = V4L2_CTRL_TYPE_INTEGER,
  2262. .name = "Signal Threshold",
  2263. .minimum = 0x80,
  2264. .maximum = 0x7F,
  2265. .step = 1,
  2266. .default_value = 0,
  2267. },
  2268. {
  2269. .id = V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY,
  2270. .type = V4L2_CTRL_TYPE_INTEGER,
  2271. .name = "Search PTY",
  2272. .minimum = 0,
  2273. .maximum = 31,
  2274. .default_value = 0,
  2275. },
  2276. {
  2277. .id = V4L2_CID_PRIVATE_TAVARUA_SRCH_PI,
  2278. .type = V4L2_CTRL_TYPE_INTEGER,
  2279. .name = "Search PI",
  2280. .minimum = 0,
  2281. .maximum = 0xFF,
  2282. .default_value = 0,
  2283. },
  2284. {
  2285. .id = V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT,
  2286. .type = V4L2_CTRL_TYPE_INTEGER,
  2287. .name = "Preset num",
  2288. .minimum = 0,
  2289. .maximum = 12,
  2290. .default_value = 0,
  2291. },
  2292. {
  2293. .id = V4L2_CID_PRIVATE_TAVARUA_EMPHASIS,
  2294. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2295. .name = "Emphasis",
  2296. .minimum = 0,
  2297. .maximum = 1,
  2298. .default_value = 0,
  2299. },
  2300. {
  2301. .id = V4L2_CID_PRIVATE_TAVARUA_RDS_STD,
  2302. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2303. .name = "RDS standard",
  2304. .minimum = 0,
  2305. .maximum = 1,
  2306. .default_value = 0,
  2307. },
  2308. {
  2309. .id = V4L2_CID_PRIVATE_TAVARUA_SPACING,
  2310. .type = V4L2_CTRL_TYPE_INTEGER,
  2311. .name = "Channel spacing",
  2312. .minimum = 0,
  2313. .maximum = 2,
  2314. .default_value = 0,
  2315. },
  2316. {
  2317. .id = V4L2_CID_PRIVATE_TAVARUA_RDSON,
  2318. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2319. .name = "RDS on/off",
  2320. .minimum = 0,
  2321. .maximum = 1,
  2322. .default_value = 0,
  2323. },
  2324. {
  2325. .id = V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK,
  2326. .type = V4L2_CTRL_TYPE_INTEGER,
  2327. .name = "RDS group mask",
  2328. .minimum = 0,
  2329. .maximum = 0xFFFFFFFF,
  2330. .default_value = 0,
  2331. },
  2332. {
  2333. .id = V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC,
  2334. .type = V4L2_CTRL_TYPE_INTEGER,
  2335. .name = "RDS processing",
  2336. .minimum = 0,
  2337. .maximum = 0xFF,
  2338. .default_value = 0,
  2339. },
  2340. {
  2341. .id = V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF,
  2342. .type = V4L2_CTRL_TYPE_INTEGER,
  2343. .name = "RDS data groups to buffer",
  2344. .minimum = 1,
  2345. .maximum = 21,
  2346. .default_value = 0,
  2347. },
  2348. {
  2349. .id = V4L2_CID_PRIVATE_TAVARUA_PSALL,
  2350. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2351. .name = "pass all ps strings",
  2352. .minimum = 0,
  2353. .maximum = 1,
  2354. .default_value = 0,
  2355. },
  2356. {
  2357. .id = V4L2_CID_PRIVATE_TAVARUA_LP_MODE,
  2358. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2359. .name = "Low power mode",
  2360. .minimum = 0,
  2361. .maximum = 1,
  2362. .default_value = 0,
  2363. },
  2364. {
  2365. .id = V4L2_CID_PRIVATE_TAVARUA_ANTENNA,
  2366. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2367. .name = "headset/internal",
  2368. .minimum = 0,
  2369. .maximum = 1,
  2370. .default_value = 0,
  2371. },
  2372. /* Private controls for FM TX*/
  2373. {
  2374. .id = V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT,
  2375. .type = V4L2_CTRL_TYPE_INTEGER,
  2376. .name = "Set PS REPEATCOUNT",
  2377. .minimum = 0,
  2378. .maximum = 15,
  2379. },
  2380. {
  2381. .id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME,
  2382. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2383. .name = "Stop PS NAME",
  2384. .minimum = 0,
  2385. .maximum = 1,
  2386. },
  2387. {
  2388. .id = V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT,
  2389. .type = V4L2_CTRL_TYPE_BOOLEAN,
  2390. .name = "Stop RT",
  2391. .minimum = 0,
  2392. .maximum = 1,
  2393. },
  2394. { .id = V4L2_CID_PRIVATE_SET_NOTCH_FILTER,
  2395. .type = V4L2_CTRL_TYPE_INTEGER,
  2396. .name = "Notch filter",
  2397. .minimum = 0,
  2398. .maximum = 2,
  2399. },
  2400. };
  2401. /*=============================================================================
  2402. FUNCTION: tavarua_vidioc_querycap
  2403. =============================================================================*/
  2404. /**
  2405. This function is called to query device capabilities.
  2406. NOTE:
  2407. All V4L2 devices support the VIDIOC_QUERYCAP ioctl. It is used to identify
  2408. kernel devices compatible with this specification and to obtain information
  2409. about driver and hardware capabilities. The ioctl takes a pointer to a struct
  2410. v4l2_capability which is filled by the driver. When the driver is not
  2411. compatible with this specification the ioctl returns an EINVAL error code.
  2412. @param file: File descriptor returned by open().
  2413. @param capability: pointer to struct v4l2_capability.
  2414. @return On success 0 is returned, else error code.
  2415. @return EINVAL: The device is not compatible with this specification.
  2416. */
  2417. static int tavarua_vidioc_querycap(struct file *file, void *priv,
  2418. struct v4l2_capability *capability)
  2419. {
  2420. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  2421. if (unlikely(radio == NULL)) {
  2422. FMDERR("%s:radio is null", __func__);
  2423. return -EINVAL;
  2424. }
  2425. if (unlikely(capability == NULL)) {
  2426. FMDERR("%s:capability is null", __func__);
  2427. return -EINVAL;
  2428. }
  2429. strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
  2430. strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
  2431. sprintf(capability->bus_info, "I2C");
  2432. capability->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
  2433. capability->version = radio->chipID;
  2434. return 0;
  2435. }
  2436. /*=============================================================================
  2437. FUNCTION: tavarua_vidioc_queryctrl
  2438. =============================================================================*/
  2439. /**
  2440. This function is called to query the device and driver for supported video
  2441. controls (enumerate control items).
  2442. NOTE:
  2443. To query the attributes of a control, the applications set the id field of
  2444. a struct v4l2_queryctrl and call the VIDIOC_QUERYCTRL ioctl with a pointer
  2445. to this structure. The driver fills the rest of the structure or returns an
  2446. EINVAL error code when the id is invalid.
  2447. @param file: File descriptor returned by open().
  2448. @param qc: pointer to struct v4l2_queryctrl.
  2449. @return On success 0 is returned, else error code.
  2450. @return EINVAL: The struct v4l2_queryctrl id is invalid.
  2451. */
  2452. static int tavarua_vidioc_queryctrl(struct file *file, void *priv,
  2453. struct v4l2_queryctrl *qc)
  2454. {
  2455. unsigned char i;
  2456. int retval = -EINVAL;
  2457. if (unlikely(qc == NULL)) {
  2458. FMDERR("%s:qc is null", __func__);
  2459. return -EINVAL;
  2460. }
  2461. for (i = 0; i < ARRAY_SIZE(tavarua_v4l2_queryctrl); i++) {
  2462. if (qc->id && qc->id == tavarua_v4l2_queryctrl[i].id) {
  2463. memcpy(qc, &(tavarua_v4l2_queryctrl[i]), sizeof(*qc));
  2464. retval = 0;
  2465. break;
  2466. }
  2467. }
  2468. if (retval < 0)
  2469. printk(KERN_WARNING DRIVER_NAME
  2470. ": query conv4ltrol failed with %d\n", retval);
  2471. return retval;
  2472. }
  2473. static int update_spur_table(struct tavarua_device *radio)
  2474. {
  2475. unsigned char xfr_buf[XFR_REG_NUM];
  2476. unsigned char size = 0, tbl_size = 0;
  2477. int index = 0, offset = 0, addr = 0x0, val = 0;
  2478. int retval = 0, temp = 0, cnt = 0, j = 0;
  2479. if (unlikely(radio == NULL)) {
  2480. FMDERR("%s:radio is null", __func__);
  2481. return -EINVAL;
  2482. }
  2483. memset(xfr_buf, 0x0, XFR_REG_NUM);
  2484. /* Read the SPUR Table Size */
  2485. retval = xfr_rdwr_data(radio, XFR_READ, 1, SPUR_TABLE_ADDR, &tbl_size);
  2486. if (retval < 0) {
  2487. FMDERR("%s: Failed to read SPUR table size\n", __func__);
  2488. return retval;
  2489. }
  2490. /* Calculate the new SPUR Register address */
  2491. val = addr = (SPUR_TABLE_START_ADDR + (tbl_size * 3));
  2492. /* Save the SPUR Table length configured by user*/
  2493. temp = radio->spur_table_size;
  2494. /* COnfigure the new spur table length */
  2495. size = (radio->spur_table_size + tbl_size);
  2496. retval = xfr_rdwr_data(radio, XFR_WRITE, 1, SPUR_TABLE_ADDR, &size);
  2497. if (retval < 0) {
  2498. FMDERR("%s: Failed to configure SPUR table size\n", __func__);
  2499. return retval;
  2500. }
  2501. /* Program the spur table entries */
  2502. for (cnt = 0; cnt < (temp / 4); cnt++) {
  2503. offset = 0;
  2504. for (j = 0; j < 4; j++) {
  2505. xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
  2506. radio->spur_data.freq[index]), 1);
  2507. xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
  2508. radio->spur_data.freq[index]), 0);
  2509. xfr_buf[offset++] =
  2510. radio->spur_data.rmssi[index];
  2511. index++;
  2512. }
  2513. retval = xfr_rdwr_data(radio, XFR_WRITE, (SPUR_DATA_SIZE * 4),
  2514. addr, xfr_buf);
  2515. if (retval < 0) {
  2516. FMDERR("%s: Failed to program SPUR frequencies\n",
  2517. __func__);
  2518. return retval;
  2519. }
  2520. addr += (SPUR_DATA_SIZE * 4);
  2521. }
  2522. /* Program the additional SPUR Frequencies */
  2523. temp = radio->spur_table_size;
  2524. temp = (temp % 4);
  2525. if (temp > 0) {
  2526. offset = 0;
  2527. for (j = 0; j < temp; j++) {
  2528. xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
  2529. radio->spur_data.freq[index]), 1);
  2530. xfr_buf[offset++] = GET_FREQ(COMPUTE_SPUR(
  2531. radio->spur_data.freq[index]), 0);
  2532. xfr_buf[offset++] =
  2533. radio->spur_data.rmssi[index];
  2534. index++;
  2535. }
  2536. size = (temp * SPUR_DATA_SIZE);
  2537. retval = xfr_rdwr_data(radio, XFR_WRITE, size, addr, xfr_buf);
  2538. if (retval < 0) {
  2539. FMDERR("%s: Failed to program SPUR frequencies\n",
  2540. __func__);
  2541. return retval;
  2542. }
  2543. }
  2544. return retval;
  2545. }
  2546. static int xfr_rdwr_data(struct tavarua_device *radio, int op, int size,
  2547. unsigned long offset, unsigned char *buf) {
  2548. unsigned char xfr_buf[XFR_REG_NUM + 1];
  2549. int retval = 0, temp = 0;
  2550. if (unlikely(radio == NULL)) {
  2551. FMDERR("%s:radio is null", __func__);
  2552. return -EINVAL;
  2553. }
  2554. if (unlikely(buf == NULL)) {
  2555. FMDERR("%s:buf is null", __func__);
  2556. return -EINVAL;
  2557. }
  2558. /* zero initialize the buffer */
  2559. memset(xfr_buf, 0x0, XFR_REG_NUM);
  2560. /* save the 'size' parameter */
  2561. temp = size;
  2562. /* Populate the XFR bytes */
  2563. xfr_buf[XFR_MODE_OFFSET] = LSH_DATA(size, 1);
  2564. xfr_buf[XFR_ADDR_MSB_OFFSET] = GET_FREQ(offset, 1);
  2565. xfr_buf[XFR_ADDR_LSB_OFFSET] = GET_FREQ(offset, 0);
  2566. if (op == XFR_READ) {
  2567. if (size > XFR_REG_NUM) {
  2568. FMDERR("%s: Cant read more than 16 bytes\n", __func__);
  2569. return -EINVAL;
  2570. }
  2571. xfr_buf[XFR_MODE_OFFSET] |= (XFR_PEEK_MODE);
  2572. size = 3;
  2573. } else if (op == XFR_WRITE) {
  2574. if (size > (XFR_REG_NUM - 2)) {
  2575. FMDERR("%s: Cant write more than 14 bytes\n", __func__);
  2576. return -EINVAL;
  2577. }
  2578. xfr_buf[XFR_MODE_OFFSET] |= (XFR_POKE_MODE);
  2579. memcpy(&xfr_buf[XFR_DATA_OFFSET], buf, size);
  2580. size += 3;
  2581. }
  2582. /* Perform the XFR READ/WRITE operation */
  2583. init_completion(&radio->sync_req_done);
  2584. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, size);
  2585. if (retval < 0) {
  2586. FMDERR("%s: Failed to perform XFR operation\n", __func__);
  2587. return retval;
  2588. }
  2589. /*Wait for the XFR interrupt */
  2590. if (!wait_for_completion_timeout(&radio->sync_req_done,
  2591. msecs_to_jiffies(WAIT_TIMEOUT))) {
  2592. FMDERR("Timeout: No XFR interrupt");
  2593. return -ETIMEDOUT;
  2594. }
  2595. /*
  2596. * For XFR READ operation save the XFR data provided by the SOC.
  2597. * Firmware reads the data from the address specified and places
  2598. * them in to the registers XFRDAT0-XFRDAT15 which the host can read.
  2599. */
  2600. size = temp;
  2601. if (op == XFR_READ) {
  2602. retval = tavarua_read_registers(radio, XFRDAT0, size);
  2603. if (retval < 0) {
  2604. FMDERR("%s: Failed to read the XFR data\n", __func__);
  2605. return retval;
  2606. }
  2607. if (buf != NULL)
  2608. memcpy(buf, &radio->registers[XFRDAT0], size);
  2609. else {
  2610. FMDERR("%s: No buffer to copy XFR data\n", __func__);
  2611. return -EINVAL;
  2612. }
  2613. }
  2614. return retval;
  2615. }
  2616. static int peek_MPX_DCC(struct tavarua_device *radio)
  2617. {
  2618. int retval = 0;
  2619. unsigned char xfr_buf[XFR_REG_NUM];
  2620. int MPX_DCC[] = { 0 };
  2621. int DCC = 0;
  2622. int ct = 0;
  2623. unsigned char size = 0;
  2624. if (unlikely(radio == NULL)) {
  2625. FMDERR("%s:radio is null", __func__);
  2626. return -EINVAL;
  2627. }
  2628. /*
  2629. Poking the MPX_DCC_BYPASS register to freeze the
  2630. value of MPX_DCC from changing while we access it
  2631. */
  2632. /*Poking the MPX_DCC_BYPASS register : 0x88C0 */
  2633. size = 0x01;
  2634. xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
  2635. xfr_buf[1] = MPX_DCC_BYPASS_POKE_MSB;
  2636. xfr_buf[2] = MPX_DCC_BYPASS_POKE_LSB;
  2637. xfr_buf[3] = 0x01;
  2638. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 4);
  2639. if (retval < 0) {
  2640. FMDBG("Failed to write\n");
  2641. return retval;
  2642. }
  2643. /*Wait for the XFR interrupt */
  2644. msleep(TAVARUA_DELAY*15);
  2645. for (ct = 0; ct < 5; ct++)
  2646. xfr_buf[ct] = 0;
  2647. /* Peeking Regs 0x88C2-0x88C4 */
  2648. size = 0x03;
  2649. xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
  2650. xfr_buf[1] = MPX_DCC_PEEK_MSB_REG1;
  2651. xfr_buf[2] = MPX_DCC_PEEK_LSB_REG1;
  2652. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
  2653. if (retval < 0) {
  2654. FMDBG("Failed to write\n");
  2655. return retval;
  2656. }
  2657. /*Wait for the XFR interrupt */
  2658. msleep(TAVARUA_DELAY*10);
  2659. retval = tavarua_read_registers(radio, XFRDAT0, 3);
  2660. if (retval < 0) {
  2661. printk(KERN_INFO "INT_DET: Read failure\n");
  2662. return retval;
  2663. }
  2664. MPX_DCC[0] = (int)radio->registers[XFRDAT0];
  2665. MPX_DCC[1] = (int)radio->registers[XFRDAT1];
  2666. MPX_DCC[2] = (int)radio->registers[XFRDAT2];
  2667. /*
  2668. Form the final MPX_DCC parameter
  2669. MPX_DCC[0] will form the LSB part
  2670. MPX_DCC[1] will be the middle part and 4 bits of
  2671. MPX_DCC[2] will be the MSB par of the 20-bit signed MPX_DCC
  2672. */
  2673. DCC = ((int)MPX_DCC[2] << 16) | ((int)MPX_DCC[1] << 8) |
  2674. ((int)MPX_DCC[0]);
  2675. /*
  2676. if bit-19 is '1',set remaining bits to '1' & make it -tive
  2677. */
  2678. if (DCC & 0x00080000) {
  2679. FMDBG(KERN_INFO "bit-19 is '1'\n");
  2680. DCC |= 0xFFF00000;
  2681. }
  2682. /*
  2683. Poking the MPX_DCC_BYPASS register to be back to normal
  2684. */
  2685. /*Poking the MPX_DCC_BYPASS register : 0x88C0 */
  2686. size = 0x01;
  2687. xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
  2688. xfr_buf[1] = MPX_DCC_BYPASS_POKE_MSB;
  2689. xfr_buf[2] = MPX_DCC_BYPASS_POKE_LSB;
  2690. xfr_buf[3] = 0x00;
  2691. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 4);
  2692. if (retval < 0) {
  2693. FMDBG("Failed to write\n");
  2694. return retval;
  2695. }
  2696. /*Wait for the XFR interrupt */
  2697. msleep(TAVARUA_DELAY*10);
  2698. return DCC;
  2699. }
  2700. /*=============================================================================
  2701. FUNCTION: tavarua_vidioc_g_ctrl
  2702. =============================================================================*/
  2703. /**
  2704. This function is called to get the value of a control.
  2705. NOTE:
  2706. To get the current value of a control, applications initialize the id field
  2707. of a struct v4l2_control and call the VIDIOC_G_CTRL ioctl with a pointer to
  2708. this structure.
  2709. When the id is invalid drivers return an EINVAL error code. When the value is
  2710. out of bounds drivers can choose to take the closest valid value or return an
  2711. ERANGE error code, whatever seems more appropriate.
  2712. @param file: File descriptor returned by open().
  2713. @param ctrl: pointer to struct v4l2_control.
  2714. @return On success 0 is returned, else error code.
  2715. @return EINVAL: The struct v4l2_control id is invalid.
  2716. @return ERANGE: The struct v4l2_control value is out of bounds.
  2717. @return EBUSY: The control is temporarily not changeable, possibly because
  2718. another applications took over control of the device function this control
  2719. belongs to.
  2720. */
  2721. static int tavarua_vidioc_g_ctrl(struct file *file, void *priv,
  2722. struct v4l2_control *ctrl)
  2723. {
  2724. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  2725. int retval = 0;
  2726. int cnt = 0;
  2727. unsigned char xfr_buf[XFR_REG_NUM];
  2728. signed char cRmssiThreshold;
  2729. signed char ioc;
  2730. unsigned char size = 0;
  2731. if (unlikely(radio == NULL)) {
  2732. FMDERR("%s:radio is null", __func__);
  2733. return -EINVAL;
  2734. }
  2735. if (unlikely(ctrl == NULL)) {
  2736. FMDERR("%s:ctrl is null", __func__);
  2737. return -EINVAL;
  2738. }
  2739. switch (ctrl->id) {
  2740. case V4L2_CID_AUDIO_VOLUME:
  2741. break;
  2742. case V4L2_CID_AUDIO_MUTE:
  2743. ctrl->value = radio->registers[IOCTRL] & 0x03 ;
  2744. break;
  2745. case V4L2_CID_PRIVATE_TAVARUA_SRCHMODE:
  2746. ctrl->value = radio->registers[SRCHCTRL] & SRCH_MODE;
  2747. break;
  2748. case V4L2_CID_PRIVATE_TAVARUA_SCANDWELL:
  2749. ctrl->value = (radio->registers[SRCHCTRL] & SCAN_DWELL) >> 4;
  2750. break;
  2751. case V4L2_CID_PRIVATE_TAVARUA_SRCHON:
  2752. ctrl->value = (radio->registers[SRCHCTRL] & SRCH_ON) >> 7 ;
  2753. break;
  2754. case V4L2_CID_PRIVATE_TAVARUA_STATE:
  2755. ctrl->value = (radio->registers[RDCTRL] & 0x03);
  2756. break;
  2757. case V4L2_CID_PRIVATE_TAVARUA_IOVERC:
  2758. retval = tavarua_read_registers(radio, IOVERC, 1);
  2759. if (retval < 0)
  2760. return retval;
  2761. ioc = radio->registers[IOVERC];
  2762. ctrl->value = ioc;
  2763. break;
  2764. case V4L2_CID_PRIVATE_TAVARUA_INTDET:
  2765. size = 0x1;
  2766. xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
  2767. xfr_buf[1] = INTDET_PEEK_MSB;
  2768. xfr_buf[2] = INTDET_PEEK_LSB;
  2769. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
  2770. if (retval < 0) {
  2771. FMDBG("Failed to write\n");
  2772. return retval;
  2773. }
  2774. FMDBG("INT_DET:Sync write success\n");
  2775. /*Wait for the XFR interrupt */
  2776. msleep(TAVARUA_DELAY*10);
  2777. /* Read the XFRDAT0 register populated by FM SoC */
  2778. retval = tavarua_read_registers(radio, XFRDAT0, 3);
  2779. if (retval < 0) {
  2780. FMDBG("INT_DET: Read failure\n");
  2781. return retval;
  2782. }
  2783. ctrl->value = radio->registers[XFRDAT0];
  2784. break;
  2785. case V4L2_CID_PRIVATE_TAVARUA_MPX_DCC:
  2786. ctrl->value = peek_MPX_DCC(radio);
  2787. break;
  2788. case V4L2_CID_PRIVATE_TAVARUA_REGION:
  2789. ctrl->value = radio->region_params.region;
  2790. break;
  2791. case V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH:
  2792. retval = sync_read_xfr(radio, RX_CONFIG, xfr_buf);
  2793. if (retval < 0) {
  2794. FMDBG("[G IOCTL=V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH]\n");
  2795. FMDBG("sync_read_xfr error: [retval=%d]\n", retval);
  2796. break;
  2797. }
  2798. /* Since RMSSI Threshold is signed value */
  2799. cRmssiThreshold = (signed char)xfr_buf[0];
  2800. ctrl->value = cRmssiThreshold;
  2801. FMDBG("cRmssiThreshold: %d\n", cRmssiThreshold);
  2802. break;
  2803. case V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY:
  2804. ctrl->value = radio->srch_params.srch_pty;
  2805. break;
  2806. case V4L2_CID_PRIVATE_TAVARUA_SRCH_PI:
  2807. ctrl->value = radio->srch_params.srch_pi;
  2808. break;
  2809. case V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT:
  2810. ctrl->value = radio->srch_params.preset_num;
  2811. break;
  2812. case V4L2_CID_PRIVATE_TAVARUA_EMPHASIS:
  2813. ctrl->value = radio->region_params.emphasis;
  2814. break;
  2815. case V4L2_CID_PRIVATE_TAVARUA_RDS_STD:
  2816. ctrl->value = radio->region_params.rds_std;
  2817. break;
  2818. case V4L2_CID_PRIVATE_TAVARUA_SPACING:
  2819. ctrl->value = radio->region_params.spacing;
  2820. break;
  2821. case V4L2_CID_PRIVATE_TAVARUA_RDSON:
  2822. ctrl->value = radio->registers[RDSCTRL] & RDS_ON;
  2823. break;
  2824. case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK:
  2825. retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
  2826. if (retval > -1)
  2827. ctrl->value = (xfr_buf[8] << 24) |
  2828. (xfr_buf[9] << 16) |
  2829. (xfr_buf[10] << 8) |
  2830. xfr_buf[11];
  2831. break;
  2832. case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC:
  2833. retval = tavarua_read_registers(radio, ADVCTRL, 1);
  2834. if (retval > -1)
  2835. ctrl->value = radio->registers[ADVCTRL];
  2836. msleep(TAVARUA_DELAY*5);
  2837. break;
  2838. case V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA:
  2839. retval = sync_read_xfr(radio, RX_CONFIG, xfr_buf);
  2840. if (retval < 0) {
  2841. FMDERR("V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA]\n");
  2842. FMDERR("sync_read_xfr [retval=%d]\n", retval);
  2843. break;
  2844. }
  2845. ctrl->value = (unsigned char)xfr_buf[4];
  2846. break;
  2847. case V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF:
  2848. retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
  2849. if (retval > -1)
  2850. ctrl->value = xfr_buf[1];
  2851. break;
  2852. case V4L2_CID_PRIVATE_TAVARUA_PSALL:
  2853. retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
  2854. if (retval > -1)
  2855. ctrl->value = xfr_buf[12] & RDS_CONFIG_PSALL;
  2856. break;
  2857. case V4L2_CID_PRIVATE_TAVARUA_LP_MODE:
  2858. ctrl->value = radio->lp_mode;
  2859. break;
  2860. case V4L2_CID_PRIVATE_TAVARUA_ANTENNA:
  2861. ctrl->value = GET_REG_FIELD(radio->registers[IOCTRL],
  2862. IOC_ANTENNA_OFFSET, IOC_ANTENNA_MASK);
  2863. break;
  2864. case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
  2865. size = 0x04;
  2866. xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
  2867. xfr_buf[1] = ON_CHANNEL_TH_MSB;
  2868. xfr_buf[2] = ON_CHANNEL_TH_LSB;
  2869. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
  2870. if (retval < 0) {
  2871. pr_err("%s: Failed to write\n", __func__);
  2872. return retval;
  2873. }
  2874. /*Wait for the XFR interrupt */
  2875. msleep(TAVARUA_DELAY*10);
  2876. retval = tavarua_read_registers(radio, XFRDAT0, 4);
  2877. if (retval < 0) {
  2878. pr_err("%s: On Ch. DET: Read failure\n", __func__);
  2879. return retval;
  2880. }
  2881. for (cnt = 0; cnt < 4; cnt++)
  2882. FMDBG("On-Channel data set is : 0x%x\t",
  2883. (int)radio->registers[XFRDAT0+cnt]);
  2884. ctrl->value = LSH_DATA(radio->registers[XFRDAT0], 24) |
  2885. LSH_DATA(radio->registers[XFRDAT0+1], 16) |
  2886. LSH_DATA(radio->registers[XFRDAT0+2], 8) |
  2887. (radio->registers[XFRDAT0+3]);
  2888. FMDBG("The On Channel Threshold value is : 0x%x", ctrl->value);
  2889. break;
  2890. case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
  2891. size = 0x04;
  2892. xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
  2893. xfr_buf[1] = OFF_CHANNEL_TH_MSB;
  2894. xfr_buf[2] = OFF_CHANNEL_TH_LSB;
  2895. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
  2896. if (retval < 0) {
  2897. pr_err("%s: Failed to write\n", __func__);
  2898. return retval;
  2899. }
  2900. /*Wait for the XFR interrupt */
  2901. msleep(TAVARUA_DELAY*10);
  2902. retval = tavarua_read_registers(radio, XFRDAT0, 4);
  2903. if (retval < 0) {
  2904. pr_err("%s: Off Ch. DET: Read failure\n", __func__);
  2905. return retval;
  2906. }
  2907. for (cnt = 0; cnt < 4; cnt++)
  2908. FMDBG("Off-channel data set is : 0x%x\t",
  2909. (int)radio->registers[XFRDAT0+cnt]);
  2910. ctrl->value = LSH_DATA(radio->registers[XFRDAT0], 24) |
  2911. LSH_DATA(radio->registers[XFRDAT0+1], 16) |
  2912. LSH_DATA(radio->registers[XFRDAT0+2], 8) |
  2913. (radio->registers[XFRDAT0+3]);
  2914. FMDBG("The Off Channel Threshold value is : 0x%x", ctrl->value);
  2915. break;
  2916. /*
  2917. * These IOCTL's are place holders to keep the
  2918. * driver compatible with change in frame works for IRIS
  2919. */
  2920. case V4L2_CID_PRIVATE_SINR_THRESHOLD:
  2921. case V4L2_CID_PRIVATE_SINR_SAMPLES:
  2922. case V4L2_CID_PRIVATE_IRIS_GET_SINR:
  2923. retval = 0;
  2924. break;
  2925. case V4L2_CID_PRIVATE_VALID_CHANNEL:
  2926. ctrl->value = radio->is_station_valid;
  2927. break;
  2928. default:
  2929. retval = -EINVAL;
  2930. }
  2931. if (retval < 0)
  2932. printk(KERN_WARNING DRIVER_NAME
  2933. ": get control failed with %d, id: %d\n", retval, ctrl->id);
  2934. return retval;
  2935. }
  2936. static int tavarua_vidioc_s_ext_ctrls(struct file *file, void *priv,
  2937. struct v4l2_ext_controls *ctrl)
  2938. {
  2939. int retval = 0;
  2940. int bytes_to_copy;
  2941. int bytes_copied = 0;
  2942. __u32 bytes_left = 0;
  2943. int chunk_index = 0;
  2944. char tx_data[XFR_REG_NUM];
  2945. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  2946. char *data = NULL;
  2947. int extra_name_byte = 0;
  2948. int name_bytes = 0;
  2949. if (unlikely(radio == NULL)) {
  2950. FMDERR("%s:radio is null", __func__);
  2951. return -EINVAL;
  2952. }
  2953. if (unlikely(ctrl == NULL) ||
  2954. unlikely(ctrl->controls == NULL) ||
  2955. unlikely(ctrl->count <= 0)) {
  2956. FMDERR("%s:ctrl is null", __func__);
  2957. return -EINVAL;
  2958. }
  2959. switch ((ctrl->controls[0]).id) {
  2960. case V4L2_CID_RDS_TX_PS_NAME: {
  2961. FMDBG("In V4L2_CID_RDS_TX_PS_NAME\n");
  2962. /*Pass a sample PS string */
  2963. chunk_index = 0;
  2964. bytes_copied = 0;
  2965. bytes_left = min((ctrl->controls[0]).size,
  2966. (__u32)MAX_PS_LENGTH);
  2967. data = (ctrl->controls[0]).string;
  2968. /* send payload to FM hardware */
  2969. while (bytes_left) {
  2970. chunk_index++;
  2971. FMDBG("chunk is %d", chunk_index);
  2972. bytes_to_copy = min(bytes_left, (__u32)XFR_REG_NUM);
  2973. /*Clear the tx_data */
  2974. memset(tx_data, 0, XFR_REG_NUM);
  2975. if (copy_from_user(tx_data,
  2976. data + bytes_copied, bytes_to_copy))
  2977. return -EFAULT;
  2978. retval = sync_write_xfr(radio,
  2979. RDS_PS_0 + chunk_index, tx_data);
  2980. if (retval < 0) {
  2981. FMDBG("sync_write_xfr: %d", retval);
  2982. return retval;
  2983. }
  2984. bytes_copied += bytes_to_copy;
  2985. bytes_left -= bytes_to_copy;
  2986. }
  2987. memset(tx_data, 0, XFR_REG_NUM);
  2988. /*Write the PS Header*/
  2989. FMDBG("Writing PS header\n");
  2990. extra_name_byte = (bytes_copied%8) ? 1 : 0;
  2991. name_bytes = (bytes_copied/8) + extra_name_byte;
  2992. /*8 bytes are grouped as 1 name */
  2993. tx_data[0] = (name_bytes) & MASK_TXREPCOUNT;
  2994. tx_data[1] = radio->pty & MASK_PTY; /* PTY */
  2995. tx_data[2] = ((radio->pi & MASK_PI_MSB) >> 8);
  2996. tx_data[3] = radio->pi & MASK_PI_LSB;
  2997. /* TX ctrl + repeatCount*/
  2998. tx_data[4] = TX_ON |
  2999. (radio->ps_repeatcount & MASK_TXREPCOUNT);
  3000. retval = sync_write_xfr(radio, RDS_PS_0, tx_data);
  3001. if (retval < 0) {
  3002. FMDBG("sync_write_xfr returned %d", retval);
  3003. return retval;
  3004. }
  3005. } break;
  3006. case V4L2_CID_RDS_TX_RADIO_TEXT: {
  3007. chunk_index = 0;
  3008. bytes_copied = 0;
  3009. FMDBG("In V4L2_CID_RDS_TX_RADIO_TEXT\n");
  3010. /*Pass a sample PS string */
  3011. FMDBG("Passed RT String : %s\n",
  3012. (ctrl->controls[0]).string);
  3013. bytes_left =
  3014. min((ctrl->controls[0]).size, (__u32)MAX_RT_LENGTH);
  3015. data = (ctrl->controls[0]).string;
  3016. /* send payload to FM hardware */
  3017. while (bytes_left) {
  3018. chunk_index++;
  3019. bytes_to_copy = min(bytes_left, (__u32)XFR_REG_NUM);
  3020. memset(tx_data, 0, XFR_REG_NUM);
  3021. if (copy_from_user(tx_data,
  3022. data + bytes_copied, bytes_to_copy))
  3023. return -EFAULT;
  3024. retval = sync_write_xfr(radio,
  3025. RDS_RT_0 + chunk_index, tx_data);
  3026. if (retval < 0)
  3027. return retval;
  3028. bytes_copied += bytes_to_copy;
  3029. bytes_left -= bytes_to_copy;
  3030. }
  3031. /*Write the RT Header */
  3032. tx_data[0] = bytes_copied;
  3033. /* PTY */
  3034. tx_data[1] = TX_ON | ((radio->pty & MASK_PTY) >> 8);
  3035. /* PI high */
  3036. tx_data[2] = ((radio->pi & MASK_PI_MSB) >> 8);
  3037. /* PI low */
  3038. tx_data[3] = radio->pi & MASK_PI_LSB;
  3039. retval = sync_write_xfr(radio, RDS_RT_0 , tx_data);
  3040. if (retval < 0)
  3041. return retval;
  3042. FMDBG("done RT writing: %d\n", retval);
  3043. } break;
  3044. default:
  3045. {
  3046. FMDBG("Shouldn't reach here\n");
  3047. retval = -1;
  3048. }
  3049. }
  3050. return retval;
  3051. }
  3052. /*=============================================================================
  3053. FUNCTION: tavarua_vidioc_s_ctrl
  3054. =============================================================================*/
  3055. /**
  3056. This function is called to set the value of a control.
  3057. NOTE:
  3058. To change the value of a control, applications initialize the id and value
  3059. fields of a struct v4l2_control and call the VIDIOC_S_CTRL ioctl.
  3060. When the id is invalid drivers return an EINVAL error code. When the value is
  3061. out of bounds drivers can choose to take the closest valid value or return an
  3062. ERANGE error code, whatever seems more appropriate.
  3063. @param file: File descriptor returned by open().
  3064. @param ctrl: pointer to struct v4l2_control.
  3065. @return On success 0 is returned, else error code.
  3066. @return EINVAL: The struct v4l2_control id is invalid.
  3067. @return ERANGE: The struct v4l2_control value is out of bounds.
  3068. @return EBUSY: The control is temporarily not changeable, possibly because
  3069. another applications took over control of the device function this control
  3070. belongs to.
  3071. */
  3072. static int tavarua_vidioc_s_ctrl(struct file *file, void *priv,
  3073. struct v4l2_control *ctrl)
  3074. {
  3075. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3076. int retval = 0, size = 0, cnt = 0;
  3077. unsigned char value;
  3078. unsigned char xfr_buf[XFR_REG_NUM];
  3079. unsigned char tx_data[XFR_REG_NUM];
  3080. unsigned char dis_buf[XFR_REG_NUM];
  3081. unsigned int freq = 0, mpx_dcc = 0;
  3082. unsigned long curr = 0, prev = 0;
  3083. if (unlikely(radio == NULL)) {
  3084. FMDERR("%s:radio is null", __func__);
  3085. return -EINVAL;
  3086. }
  3087. if (unlikely(ctrl == NULL)) {
  3088. FMDERR("%s:ctrl is null", __func__);
  3089. return -EINVAL;
  3090. }
  3091. memset(xfr_buf, 0x0, XFR_REG_NUM);
  3092. switch (ctrl->id) {
  3093. case V4L2_CID_AUDIO_VOLUME:
  3094. break;
  3095. case V4L2_CID_AUDIO_MUTE:
  3096. value = (radio->registers[IOCTRL] & ~IOC_HRD_MUTE) |
  3097. (ctrl->value & 0x03);
  3098. retval = tavarua_write_register(radio, IOCTRL, value);
  3099. break;
  3100. case V4L2_CID_PRIVATE_TAVARUA_SRCHMODE:
  3101. value = (radio->registers[SRCHCTRL] & ~SRCH_MODE) |
  3102. ctrl->value;
  3103. radio->registers[SRCHCTRL] = value;
  3104. break;
  3105. case V4L2_CID_PRIVATE_TAVARUA_SCANDWELL:
  3106. value = (radio->registers[SRCHCTRL] & ~SCAN_DWELL) |
  3107. (ctrl->value << 4);
  3108. radio->registers[SRCHCTRL] = value;
  3109. break;
  3110. /* start/stop search */
  3111. case V4L2_CID_PRIVATE_TAVARUA_SRCHON:
  3112. FMDBG("starting search\n");
  3113. tavarua_search(radio, ctrl->value, SRCH_DIR_UP);
  3114. break;
  3115. case V4L2_CID_PRIVATE_TAVARUA_STATE:
  3116. /* check if already on */
  3117. radio->handle_irq = 1;
  3118. if (((ctrl->value == FM_RECV) || (ctrl->value == FM_TRANS))
  3119. && !(radio->registers[RDCTRL] &
  3120. ctrl->value)) {
  3121. FMDBG("clearing flags\n");
  3122. init_completion(&radio->sync_xfr_start);
  3123. init_completion(&radio->sync_req_done);
  3124. radio->xfr_in_progress = 0;
  3125. radio->xfr_bytes_left = 0;
  3126. FMDBG("turning on ..\n");
  3127. retval = tavarua_start(radio, ctrl->value);
  3128. if (retval >= 0) {
  3129. /* Enabling 'SoftMute' & 'SignalBlending' */
  3130. value = (radio->registers[IOCTRL] |
  3131. IOC_SFT_MUTE | IOC_SIG_BLND);
  3132. retval = tavarua_write_register(radio,
  3133. IOCTRL, value);
  3134. if (retval < 0)
  3135. FMDBG("SMute and SBlending"
  3136. "not enabled\n");
  3137. }
  3138. }
  3139. /* check if off */
  3140. else if ((ctrl->value == FM_OFF) && radio->registers[RDCTRL]) {
  3141. radio->spur_table_size = 0;
  3142. FMDBG("%s: turning off...\n", __func__);
  3143. tavarua_write_register(radio, RDCTRL, ctrl->value);
  3144. /* flush the event and work queues */
  3145. kfifo_reset(&radio->data_buf[TAVARUA_BUF_EVENTS]);
  3146. flush_workqueue(radio->wqueue);
  3147. /*
  3148. * queue the READY event from the host side
  3149. * in case of FM off
  3150. */
  3151. tavarua_q_event(radio, TAVARUA_EVT_RADIO_DISABLED);
  3152. FMDBG("%s, Disable All Interrupts\n", __func__);
  3153. /* disable irq */
  3154. dis_buf[STATUS_REG1] = 0x00;
  3155. dis_buf[STATUS_REG2] = 0x00;
  3156. dis_buf[STATUS_REG3] = TRANSFER;
  3157. retval = sync_write_xfr(radio, INT_CTRL, dis_buf);
  3158. if (retval < 0) {
  3159. pr_err("%s: failed to disable"
  3160. "Interrupts\n", __func__);
  3161. return retval;
  3162. }
  3163. }
  3164. break;
  3165. case V4L2_CID_PRIVATE_TAVARUA_SET_AUDIO_PATH:
  3166. FMDBG("Setting audio path ...\n");
  3167. if (ctrl->value == FM_DIGITAL_PATH) {
  3168. FMDBG("Digital audio path enabled ...\n");
  3169. retval = tavarua_set_audio_path(
  3170. TAVARUA_AUDIO_OUT_DIGITAL_ON,
  3171. TAVARUA_AUDIO_OUT_ANALOG_OFF);
  3172. if (retval < 0) {
  3173. FMDERR("Error in tavarua_set_audio_path"
  3174. " %d\n", retval);
  3175. }
  3176. } else if (ctrl->value == FM_ANALOG_PATH) {
  3177. FMDBG("Analog audio path enabled ...\n");
  3178. retval = tavarua_set_audio_path(
  3179. TAVARUA_AUDIO_OUT_DIGITAL_OFF,
  3180. TAVARUA_AUDIO_OUT_ANALOG_ON);
  3181. if (retval < 0) {
  3182. FMDERR("Error in tavarua_set_audio_path"
  3183. " %d\n", retval);
  3184. }
  3185. }
  3186. break;
  3187. case V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM:
  3188. radio->enable_optimized_srch_alg = ctrl->value;
  3189. FMDBG("V4L2_CID_PRIVATE_TAVARUA_SRCH_ALGORITHM : %d",
  3190. radio->enable_optimized_srch_alg);
  3191. break;
  3192. case V4L2_CID_PRIVATE_TAVARUA_REGION:
  3193. retval = tavarua_set_region(radio, ctrl->value);
  3194. break;
  3195. case V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH:
  3196. retval = sync_read_xfr(radio, RX_CONFIG, xfr_buf);
  3197. if (retval < 0) {
  3198. FMDERR("V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH]\n");
  3199. FMDERR("sync_read_xfr [retval=%d]\n", retval);
  3200. break;
  3201. }
  3202. /* RMSSI Threshold is a signed 8 bit value */
  3203. xfr_buf[0] = (unsigned char)ctrl->value;
  3204. xfr_buf[1] = (unsigned char)ctrl->value;
  3205. retval = sync_write_xfr(radio, RX_CONFIG, xfr_buf);
  3206. if (retval < 0) {
  3207. FMDERR("V4L2_CID_PRIVATE_TAVARUA_SIGNAL_TH]\n");
  3208. FMDERR("sync_write_xfr [retval=%d]\n", retval);
  3209. break;
  3210. }
  3211. break;
  3212. case V4L2_CID_PRIVATE_TAVARUA_SRCH_PTY:
  3213. radio->srch_params.srch_pty = ctrl->value;
  3214. break;
  3215. case V4L2_CID_PRIVATE_TAVARUA_SRCH_PI:
  3216. radio->srch_params.srch_pi = ctrl->value;
  3217. break;
  3218. case V4L2_CID_PRIVATE_TAVARUA_SRCH_CNT:
  3219. radio->srch_params.preset_num = ctrl->value;
  3220. break;
  3221. case V4L2_CID_PRIVATE_TAVARUA_EMPHASIS:
  3222. radio->region_params.emphasis = ctrl->value;
  3223. break;
  3224. case V4L2_CID_PRIVATE_TAVARUA_RDS_STD:
  3225. radio->region_params.rds_std = ctrl->value;
  3226. break;
  3227. case V4L2_CID_PRIVATE_TAVARUA_SPACING:
  3228. radio->region_params.spacing = ctrl->value;
  3229. break;
  3230. case V4L2_CID_PRIVATE_TAVARUA_RDSON:
  3231. retval = 0;
  3232. if (ctrl->value != (radio->registers[RDSCTRL] & RDS_ON)) {
  3233. value = radio->registers[RDSCTRL] | ctrl->value;
  3234. retval = tavarua_write_register(radio, RDSCTRL, value);
  3235. }
  3236. break;
  3237. case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_MASK:
  3238. retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
  3239. if (retval < 0)
  3240. break;
  3241. xfr_buf[8] = (ctrl->value & 0xFF000000) >> 24;
  3242. xfr_buf[9] = (ctrl->value & 0x00FF0000) >> 16;
  3243. xfr_buf[10] = (ctrl->value & 0x0000FF00) >> 8;
  3244. xfr_buf[11] = (ctrl->value & 0x000000FF);
  3245. retval = sync_write_xfr(radio, RDS_CONFIG, xfr_buf);
  3246. break;
  3247. case V4L2_CID_PRIVATE_TAVARUA_RDSGROUP_PROC:
  3248. value = radio->registers[ADVCTRL] | ctrl->value;
  3249. retval = tavarua_write_register(radio, ADVCTRL, value);
  3250. break;
  3251. case V4L2_CID_PRIVATE_TAVARUA_AF_JUMP:
  3252. retval = tavarua_read_registers(radio, ADVCTRL, 1);
  3253. SET_REG_FIELD(radio->registers[ADVCTRL], ctrl->value,
  3254. RDSAF_OFFSET, RDSAF_MASK);
  3255. msleep(TAVARUA_DELAY*5);
  3256. retval = tavarua_write_register(radio,
  3257. ADVCTRL, radio->registers[ADVCTRL]);
  3258. msleep(TAVARUA_DELAY*5);
  3259. break;
  3260. case V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA:
  3261. retval = sync_read_xfr(radio, RX_CONFIG, xfr_buf);
  3262. if (retval < 0) {
  3263. FMDERR("V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA]\n");
  3264. FMDERR("sync_read_xfr [retval=%d]\n", retval);
  3265. break;
  3266. }
  3267. xfr_buf[4] = (unsigned char)ctrl->value;
  3268. retval = sync_write_xfr(radio, RX_CONFIG, xfr_buf);
  3269. if (retval < 0) {
  3270. FMDERR("V4L2_CID_PRIVATE_TAVARUA_RSSI_DELTA]\n");
  3271. FMDERR("sync_write_xfr [retval=%d]\n", retval);
  3272. break;
  3273. }
  3274. break;
  3275. case V4L2_CID_PRIVATE_TAVARUA_HLSI:
  3276. retval = tavarua_read_registers(radio, RDCTRL, 1);
  3277. SET_REG_FIELD(radio->registers[RDCTRL], ctrl->value,
  3278. RDCTRL_HLSI_OFFSET, RDCTRL_HLSI_MASK);
  3279. retval = tavarua_write_register(radio, RDCTRL,
  3280. radio->registers[RDCTRL]);
  3281. break;
  3282. case V4L2_CID_PRIVATE_TAVARUA_RDSD_BUF:
  3283. retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
  3284. if (retval < 0)
  3285. break;
  3286. xfr_buf[1] = ctrl->value;
  3287. retval = sync_write_xfr(radio, RDS_CONFIG, xfr_buf);
  3288. break;
  3289. case V4L2_CID_PRIVATE_TAVARUA_PSALL:
  3290. retval = sync_read_xfr(radio, RDS_CONFIG, xfr_buf);
  3291. value = ctrl->value & RDS_CONFIG_PSALL;
  3292. if (retval < 0)
  3293. break;
  3294. xfr_buf[12] &= ~RDS_CONFIG_PSALL;
  3295. xfr_buf[12] |= value;
  3296. retval = sync_write_xfr(radio, RDS_CONFIG, xfr_buf);
  3297. break;
  3298. case V4L2_CID_PRIVATE_TAVARUA_LP_MODE:
  3299. retval = 0;
  3300. if (ctrl->value == radio->lp_mode)
  3301. break;
  3302. if (ctrl->value) {
  3303. FMDBG("going into low power mode\n");
  3304. retval = tavarua_disable_interrupts(radio);
  3305. } else {
  3306. FMDBG("going into normal power mode\n");
  3307. tavarua_setup_interrupts(radio,
  3308. (radio->registers[RDCTRL] & 0x03));
  3309. }
  3310. break;
  3311. case V4L2_CID_PRIVATE_TAVARUA_ANTENNA:
  3312. SET_REG_FIELD(radio->registers[IOCTRL], ctrl->value,
  3313. IOC_ANTENNA_OFFSET, IOC_ANTENNA_MASK);
  3314. break;
  3315. case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
  3316. size = 0x04;
  3317. /* Poking the value of ON Channel Threshold value */
  3318. xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
  3319. xfr_buf[1] = ON_CHANNEL_TH_MSB;
  3320. xfr_buf[2] = ON_CHANNEL_TH_LSB;
  3321. /* Data to be poked into the register */
  3322. xfr_buf[3] = (ctrl->value & 0xFF000000) >> 24;
  3323. xfr_buf[4] = (ctrl->value & 0x00FF0000) >> 16;
  3324. xfr_buf[5] = (ctrl->value & 0x0000FF00) >> 8;
  3325. xfr_buf[6] = (ctrl->value & 0x000000FF);
  3326. for (cnt = 3; cnt < 7; cnt++) {
  3327. FMDBG("On-channel data to be poked is : %d",
  3328. (int)xfr_buf[cnt]);
  3329. }
  3330. retval = tavarua_write_registers(radio, XFRCTRL,
  3331. xfr_buf, size+3);
  3332. if (retval < 0) {
  3333. pr_err("%s: Failed to write\n", __func__);
  3334. return retval;
  3335. }
  3336. /*Wait for the XFR interrupt */
  3337. msleep(TAVARUA_DELAY*10);
  3338. break;
  3339. case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
  3340. size = 0x04;
  3341. /* Poking the value of OFF Channel Threshold value */
  3342. xfr_buf[0] = (XFR_POKE_MODE | (size << 1));
  3343. xfr_buf[1] = OFF_CHANNEL_TH_MSB;
  3344. xfr_buf[2] = OFF_CHANNEL_TH_LSB;
  3345. /* Data to be poked into the register */
  3346. xfr_buf[3] = (ctrl->value & 0xFF000000) >> 24;
  3347. xfr_buf[4] = (ctrl->value & 0x00FF0000) >> 16;
  3348. xfr_buf[5] = (ctrl->value & 0x0000FF00) >> 8;
  3349. xfr_buf[6] = (ctrl->value & 0x000000FF);
  3350. for (cnt = 3; cnt < 7; cnt++) {
  3351. FMDBG("Off-channel data to be poked is : %d",
  3352. (int)xfr_buf[cnt]);
  3353. }
  3354. retval = tavarua_write_registers(radio, XFRCTRL,
  3355. xfr_buf, size+3);
  3356. if (retval < 0) {
  3357. pr_err("%s: Failed to write\n", __func__);
  3358. return retval;
  3359. }
  3360. /*Wait for the XFR interrupt */
  3361. msleep(TAVARUA_DELAY*10);
  3362. break;
  3363. /* TX Controls */
  3364. case V4L2_CID_RDS_TX_PTY: {
  3365. radio->pty = ctrl->value;
  3366. } break;
  3367. case V4L2_CID_RDS_TX_PI: {
  3368. radio->pi = ctrl->value;
  3369. } break;
  3370. case V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME: {
  3371. FMDBG("In STOP_RDS_TX_PS_NAME\n");
  3372. /*Pass a sample PS string */
  3373. memset(tx_data, '0', XFR_REG_NUM);
  3374. FMDBG("Writing PS header\n");
  3375. retval = sync_write_xfr(radio, RDS_PS_0, tx_data);
  3376. FMDBG("retval of PS Header write: %d", retval);
  3377. } break;
  3378. case V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT: {
  3379. memset(tx_data, '0', XFR_REG_NUM);
  3380. FMDBG("Writing RT header\n");
  3381. retval = sync_write_xfr(radio, RDS_RT_0, tx_data);
  3382. FMDBG("retval of Header write: %d", retval);
  3383. } break;
  3384. case V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT: {
  3385. radio->ps_repeatcount = ctrl->value;
  3386. } break;
  3387. case V4L2_CID_TUNE_POWER_LEVEL: {
  3388. unsigned char tx_power_lvl_config[FM_TX_PWR_LVL_MAX+1] = {
  3389. 0x85, /* tx_da<5:3> = 0 lpf<2:0> = 5*/
  3390. 0x95, /* tx_da<5:3> = 2 lpf<2:0> = 5*/
  3391. 0x9D, /* tx_da<5:3> = 3 lpf<2:0> = 5*/
  3392. 0xA5, /* tx_da<5:3> = 4 lpf<2:0> = 5*/
  3393. 0xAD, /* tx_da<5:3> = 5 lpf<2:0> = 5*/
  3394. 0xB5, /* tx_da<5:3> = 6 lpf<2:0> = 5*/
  3395. 0xBD, /* tx_da<5:3> = 7 lpf<2:0> = 5*/
  3396. 0xBF /* tx_da<5:3> = 7 lpf<2:0> = 7*/
  3397. };
  3398. if (ctrl->value > FM_TX_PWR_LVL_MAX)
  3399. ctrl->value = FM_TX_PWR_LVL_MAX;
  3400. if (ctrl->value < FM_TX_PWR_LVL_0)
  3401. ctrl->value = FM_TX_PWR_LVL_0;
  3402. retval = sync_read_xfr(radio, PHY_TXGAIN, xfr_buf);
  3403. FMDBG("return for PHY_TXGAIN is %d", retval);
  3404. if (retval < 0) {
  3405. FMDBG("read failed");
  3406. break;
  3407. }
  3408. xfr_buf[2] = tx_power_lvl_config[ctrl->value];
  3409. retval = sync_write_xfr(radio, PHY_TXGAIN, xfr_buf);
  3410. FMDBG("return for write PHY_TXGAIN is %d", retval);
  3411. if (retval < 0)
  3412. FMDBG("write failed");
  3413. } break;
  3414. case V4L2_CID_PRIVATE_SOFT_MUTE:
  3415. radio->registers[IOCTRL] &= ~(IOC_SFT_MUTE);
  3416. if (ctrl->value)
  3417. radio->registers[IOCTRL] |= IOC_SFT_MUTE;
  3418. retval = tavarua_write_register(radio, IOCTRL,
  3419. radio->registers[IOCTRL]);
  3420. if (retval < 0)
  3421. FMDERR("Failed to enable/disable SMute\n");
  3422. break;
  3423. /*These IOCTL's are place holders to keep the
  3424. driver compatible with change in frame works for IRIS */
  3425. case V4L2_CID_PRIVATE_RIVA_ACCS_ADDR:
  3426. case V4L2_CID_PRIVATE_RIVA_ACCS_LEN:
  3427. case V4L2_CID_PRIVATE_RIVA_PEEK:
  3428. case V4L2_CID_PRIVATE_RIVA_POKE:
  3429. case V4L2_CID_PRIVATE_SSBI_ACCS_ADDR:
  3430. case V4L2_CID_PRIVATE_SSBI_PEEK:
  3431. case V4L2_CID_PRIVATE_SSBI_POKE:
  3432. case V4L2_CID_PRIVATE_RDS_GRP_COUNTERS:
  3433. case V4L2_CID_PRIVATE_SET_NOTCH_FILTER:
  3434. case V4L2_CID_PRIVATE_TAVARUA_DO_CALIBRATION:
  3435. case V4L2_CID_PRIVATE_SINR_THRESHOLD:
  3436. case V4L2_CID_PRIVATE_SINR_SAMPLES:
  3437. case V4L2_CID_PRIVATE_SPUR_SELECTION:
  3438. retval = 0;
  3439. break;
  3440. case V4L2_CID_PRIVATE_SPUR_FREQ:
  3441. radio->spur_data.freq[radio->spur_table_size] =
  3442. ctrl->value;
  3443. break;
  3444. case V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI:
  3445. radio->spur_data.rmssi[radio->spur_table_size++] =
  3446. ctrl->value;
  3447. break;
  3448. case V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE:
  3449. retval = update_spur_table(radio);
  3450. break;
  3451. case V4L2_CID_PRIVATE_TX_TONE:
  3452. retval = 0;
  3453. memset(xfr_buf, 0, sizeof(xfr_buf));
  3454. switch (ctrl->value) {
  3455. case ONE_KHZ_LR_EQUA_0DBFS:
  3456. xfr_buf[TONE_CHANNEL_EN_AND_SCALING_BYTE]
  3457. = TONE_LEFT_RIGHT_CH_ENABLED;
  3458. xfr_buf[TONE_LEFT_FREQ_BYTE] = 0x01;
  3459. xfr_buf[TONE_RIGHT_FREQ_BYTE] = 0x01;
  3460. break;
  3461. case ONE_KHZ_LEFTONLY_EQUA_0DBFS:
  3462. xfr_buf[TONE_CHANNEL_EN_AND_SCALING_BYTE]
  3463. = TONE_LEFT_CH_ENABLED;
  3464. xfr_buf[TONE_LEFT_FREQ_BYTE] = 0x01;
  3465. break;
  3466. case ONE_KHZ_RIGHTONLY_EQUA_0DBFS:
  3467. xfr_buf[TONE_CHANNEL_EN_AND_SCALING_BYTE]
  3468. = TONE_RIGHT_CH_ENABLED;
  3469. xfr_buf[TONE_RIGHT_FREQ_BYTE] = 0x01;
  3470. break;
  3471. case ONE_KHZ_LR_EQUA_l8DBFS:
  3472. xfr_buf[TONE_CHANNEL_EN_AND_SCALING_BYTE]
  3473. = (LSH_DATA(TONE_SCALE_IND_12,
  3474. TONE_SCALING_SHIFT)
  3475. | TONE_LEFT_RIGHT_CH_ENABLED);
  3476. xfr_buf[TONE_LEFT_FREQ_BYTE] = 0x01;
  3477. xfr_buf[TONE_RIGHT_FREQ_BYTE] = 0x01;
  3478. break;
  3479. case FIFTEEN_KHZ_LR_EQUA_l8DBFS:
  3480. xfr_buf[TONE_CHANNEL_EN_AND_SCALING_BYTE]
  3481. = (LSH_DATA(TONE_SCALE_IND_12,
  3482. TONE_SCALING_SHIFT)
  3483. | TONE_LEFT_RIGHT_CH_ENABLED);
  3484. xfr_buf[TONE_LEFT_FREQ_BYTE] = 0x0F;
  3485. xfr_buf[TONE_RIGHT_FREQ_BYTE] = 0x0F;
  3486. break;
  3487. default:
  3488. retval = -1;
  3489. FMDERR("tone generator value not valid\n");
  3490. break;
  3491. }
  3492. if (retval >= 0) {
  3493. xfr_buf[TONE_GEN_CTRL_BYTE] = 0x01;
  3494. retval = sync_write_xfr(radio, XFR_EXT, xfr_buf);
  3495. }
  3496. if (retval < 0)
  3497. FMDERR("Tone generator failed\n");
  3498. break;
  3499. case V4L2_CID_PRIVATE_VALID_CHANNEL:
  3500. /* Do not notify the host of tune event */
  3501. atomic_set(&radio->validate_channel, 1);
  3502. FMDBG("Going into low power mode\n");
  3503. retval = tavarua_disable_interrupts(radio);
  3504. /*
  3505. * Tune to 50KHz adjacent channel. If the requested station
  3506. * falls in JAPAN band and on the lower band-limit, then the
  3507. * adjacnet channel to be considered is 50KHz to the right side
  3508. * of the requested station as firmware does not allows to tune
  3509. * to frequency outside the range: 76000KHz to 108000KHz.
  3510. */
  3511. if (ctrl->value == REGION_JAPAN_STANDARD_BAND_LOW)
  3512. freq = (ctrl->value + ADJ_CHANNEL_KHZ);
  3513. else
  3514. freq = (ctrl->value - ADJ_CHANNEL_KHZ);
  3515. INIT_COMPLETION(radio->sync_req_done);
  3516. retval = tavarua_set_freq(radio, (freq * TUNE_MULT));
  3517. if (retval < 0) {
  3518. FMDERR("Failed to tune to adjacent station\n");
  3519. goto error;
  3520. }
  3521. if (!wait_for_completion_timeout(&radio->sync_req_done,
  3522. msecs_to_jiffies(wait_timeout))) {
  3523. FMDERR("Timeout: No Tune response\n");
  3524. retval = -ETIMEDOUT;
  3525. goto error;
  3526. }
  3527. /*
  3528. * Wait for a minimum of 100ms for the firmware
  3529. * to start collecting the MPX_DCC values
  3530. */
  3531. msleep(TAVARUA_DELAY * 10);
  3532. /* Compute MPX_DCC of adjacent station */
  3533. retval = compute_MPX_DCC(radio, &mpx_dcc);
  3534. if (retval < 0) {
  3535. FMDERR("Failed to get MPX_DCC of adjacent station\n");
  3536. goto error;
  3537. }
  3538. /* Calculate the absolute value of MPX_DCC */
  3539. prev = abs(mpx_dcc);
  3540. /* Tune back to original station */
  3541. INIT_COMPLETION(radio->sync_req_done);
  3542. retval = tavarua_set_freq(radio, (ctrl->value * TUNE_MULT));
  3543. if (retval < 0) {
  3544. FMDERR("Failed to tune to requested station\n");
  3545. goto error;
  3546. }
  3547. if (!wait_for_completion_timeout(&radio->sync_req_done,
  3548. msecs_to_jiffies(wait_timeout))) {
  3549. FMDERR("Timeout: No Tune response\n");
  3550. retval = -ETIMEDOUT;
  3551. goto error;
  3552. }
  3553. /*
  3554. * Wait for a minimum of 100ms for the firmware
  3555. * to start collecting the MPX_DCC values
  3556. */
  3557. msleep(TAVARUA_DELAY * 10);
  3558. /* Compute MPX_DCC of current station */
  3559. retval = compute_MPX_DCC(radio, &mpx_dcc);
  3560. if (retval < 0) {
  3561. FMDERR("Failed to get MPX_DCC of current station\n");
  3562. goto error;
  3563. }
  3564. /* Calculate the absolute value of MPX_DCC */
  3565. curr = abs(mpx_dcc);
  3566. FMDBG("Going into normal power mode\n");
  3567. tavarua_setup_interrupts(radio,
  3568. (radio->registers[RDCTRL] & 0x03));
  3569. FMDBG("Absolute MPX_DCC of current station : %lu\n", curr);
  3570. FMDBG("Absolute MPX_DCC of adjacent station : %lu\n", prev);
  3571. /*
  3572. * For valid stations, the absolute MPX_DCC value will be within
  3573. * the range 0 <= MPX_DCC <= 12566 and the MPX_DCC value of the
  3574. * adjacent station will be greater than 20,000.
  3575. */
  3576. if ((curr <= MPX_DCC_LIMIT) &&
  3577. (prev > MPX_DCC_UPPER_LIMIT)) {
  3578. FMDBG("%d KHz is A VALID STATION!\n", ctrl->value);
  3579. radio->is_station_valid = VALID_CHANNEL;
  3580. } else {
  3581. FMDBG("%d KHz is NOT A VALID STATION!\n", ctrl->value);
  3582. radio->is_station_valid = INVALID_CHANNEL;
  3583. }
  3584. error:
  3585. atomic_set(&radio->validate_channel, 0);
  3586. break;
  3587. default:
  3588. retval = -EINVAL;
  3589. }
  3590. if (retval < 0)
  3591. printk(KERN_WARNING DRIVER_NAME
  3592. ": set control failed with %d, id : %d\n", retval, ctrl->id);
  3593. return retval;
  3594. }
  3595. static int compute_MPX_DCC(struct tavarua_device *radio, int *val)
  3596. {
  3597. int DCC = 0, retval = 0;
  3598. int MPX_DCC[3];
  3599. unsigned char value;
  3600. unsigned char xfr_buf[XFR_REG_NUM];
  3601. /* Freeze the MPX_DCC value from changing */
  3602. value = CTRL_ON;
  3603. retval = xfr_rdwr_data(radio, XFR_WRITE, 1, MPX_DCC_BYPASS_REG, &value);
  3604. if (retval < 0) {
  3605. FMDERR("%s: Failed to freeze MPX_DCC\n", __func__);
  3606. return retval;
  3607. }
  3608. /* Measure the MPX_DCC of current station. */
  3609. retval = xfr_rdwr_data(radio, XFR_READ, 3, MPX_DCC_DATA_REG, xfr_buf);
  3610. if (retval < 0) {
  3611. FMDERR("%s: Failed to read MPX_DCC\n", __func__);
  3612. return retval;
  3613. }
  3614. MPX_DCC[0] = xfr_buf[0];
  3615. MPX_DCC[1] = xfr_buf[1];
  3616. MPX_DCC[2] = xfr_buf[2];
  3617. /*
  3618. * Form the final MPX_DCC parameter
  3619. * MPX_DCC[0] will form the LSB part
  3620. * MPX_DCC[1] will be the middle part and 4 bits of
  3621. * MPX_DCC[2] will be the MSB part of the 20-bit signed MPX_DCC
  3622. */
  3623. DCC = (LSH_DATA(MPX_DCC[2], 16) | LSH_DATA(MPX_DCC[1], 8) | MPX_DCC[0]);
  3624. /* if bit-19 is '1',set remaining bits to '1' & make it -tive */
  3625. if (DCC & 0x00080000)
  3626. DCC |= 0xFFF00000;
  3627. *val = DCC;
  3628. /* Un-freeze the MPX_DCC value */
  3629. value = CTRL_OFF;
  3630. retval = xfr_rdwr_data(radio, XFR_WRITE, 1, 0x88C0, &value);
  3631. if (retval < 0) {
  3632. FMDERR("%s: Failed to un-freeze MPX_DCC\n", __func__);
  3633. return retval;
  3634. }
  3635. return retval;
  3636. }
  3637. /*=============================================================================
  3638. FUNCTION: tavarua_vidioc_g_tuner
  3639. =============================================================================*/
  3640. /**
  3641. This function is called to get tuner attributes.
  3642. NOTE:
  3643. To query the attributes of a tuner, applications initialize the index field
  3644. and zero out the reserved array of a struct v4l2_tuner and call the
  3645. VIDIOC_G_TUNER ioctl with a pointer to this structure. Drivers fill the rest
  3646. of the structure or return an EINVAL error code when the index is out of
  3647. bounds. To enumerate all tuners applications shall begin at index zero,
  3648. incrementing by one until the driver returns EINVAL.
  3649. @param file: File descriptor returned by open().
  3650. @param tuner: pointer to struct v4l2_tuner.
  3651. @return On success 0 is returned, else error code.
  3652. @return EINVAL: The struct v4l2_tuner index is out of bounds.
  3653. */
  3654. static int tavarua_vidioc_g_tuner(struct file *file, void *priv,
  3655. struct v4l2_tuner *tuner)
  3656. {
  3657. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3658. int retval;
  3659. unsigned char xfr_buf[XFR_REG_NUM];
  3660. char rmssi = 0;
  3661. unsigned char size = 0;
  3662. if (unlikely(radio == NULL)) {
  3663. FMDERR("%s:radio is null", __func__);
  3664. return -EINVAL;
  3665. }
  3666. if (unlikely(tuner == NULL)) {
  3667. FMDERR("%s:tuner is null", __func__);
  3668. return -EINVAL;
  3669. }
  3670. if (tuner->index > 0)
  3671. return -EINVAL;
  3672. /* read status rssi */
  3673. retval = tavarua_read_registers(radio, IOCTRL, 1);
  3674. if (retval < 0)
  3675. return retval;
  3676. /* read RMSSI */
  3677. size = 0x1;
  3678. xfr_buf[0] = (XFR_PEEK_MODE | (size << 1));
  3679. xfr_buf[1] = RMSSI_PEEK_MSB;
  3680. xfr_buf[2] = RMSSI_PEEK_LSB;
  3681. retval = tavarua_write_registers(radio, XFRCTRL, xfr_buf, 3);
  3682. msleep(TAVARUA_DELAY*10);
  3683. retval = tavarua_read_registers(radio, XFRDAT0, 3);
  3684. rmssi = radio->registers[XFRDAT0];
  3685. tuner->signal = rmssi;
  3686. strcpy(tuner->name, "FM");
  3687. tuner->type = V4L2_TUNER_RADIO;
  3688. tuner->rangelow = radio->region_params.band_low;
  3689. tuner->rangehigh = radio->region_params.band_high;
  3690. tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
  3691. tuner->capability = V4L2_TUNER_CAP_LOW;
  3692. /* Stereo indicator == Stereo (instead of Mono) */
  3693. if (radio->registers[IOCTRL] & IOC_MON_STR)
  3694. tuner->audmode = V4L2_TUNER_MODE_STEREO;
  3695. else
  3696. tuner->audmode = V4L2_TUNER_MODE_MONO;
  3697. /* automatic frequency control: -1: freq to low, 1 freq to high */
  3698. tuner->afc = 0;
  3699. return 0;
  3700. }
  3701. /*=============================================================================
  3702. FUNCTION: tavarua_vidioc_s_tuner
  3703. =============================================================================*/
  3704. /**
  3705. This function is called to set tuner attributes. Used to set mono/stereo mode.
  3706. NOTE:
  3707. Tuners have two writable properties, the audio mode and the radio frequency.
  3708. To change the audio mode, applications initialize the index, audmode and
  3709. reserved fields and call the VIDIOC_S_TUNER ioctl. This will not change the
  3710. current tuner, which is determined by the current video input. Drivers may
  3711. choose a different audio mode if the requested mode is invalid or unsupported.
  3712. Since this is a write-only ioctl, it does not return the actually selected
  3713. audio mode.
  3714. To change the radio frequency the VIDIOC_S_FREQUENCY ioctl is available.
  3715. @param file: File descriptor returned by open().
  3716. @param tuner: pointer to struct v4l2_tuner.
  3717. @return On success 0 is returned, else error code.
  3718. @return -EINVAL: The struct v4l2_tuner index is out of bounds.
  3719. */
  3720. static int tavarua_vidioc_s_tuner(struct file *file, void *priv,
  3721. struct v4l2_tuner *tuner)
  3722. {
  3723. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3724. int retval;
  3725. int audmode;
  3726. if (unlikely(radio == NULL)) {
  3727. FMDERR("%s:radio is null", __func__);
  3728. return -EINVAL;
  3729. }
  3730. if (unlikely(tuner == NULL)) {
  3731. FMDERR("%s:tuner is null", __func__);
  3732. return -EINVAL;
  3733. }
  3734. if (tuner->index > 0)
  3735. return -EINVAL;
  3736. FMDBG("%s: set low to %d\n", __func__, tuner->rangelow);
  3737. radio->region_params.band_low = tuner->rangelow;
  3738. radio->region_params.band_high = tuner->rangehigh;
  3739. if (tuner->audmode == V4L2_TUNER_MODE_MONO)
  3740. /* Mono */
  3741. audmode = (radio->registers[IOCTRL] | IOC_MON_STR);
  3742. else
  3743. /* Stereo */
  3744. audmode = (radio->registers[IOCTRL] & ~IOC_MON_STR);
  3745. retval = tavarua_write_register(radio, IOCTRL, audmode);
  3746. if (retval < 0)
  3747. printk(KERN_WARNING DRIVER_NAME
  3748. ": set tuner failed with %d\n", retval);
  3749. return retval;
  3750. }
  3751. /*=============================================================================
  3752. FUNCTION: tavarua_vidioc_g_frequency
  3753. =============================================================================*/
  3754. /**
  3755. This function is called to get tuner or modulator radio frequency.
  3756. NOTE:
  3757. To get the current tuner or modulator radio frequency applications set the
  3758. tuner field of a struct v4l2_frequency to the respective tuner or modulator
  3759. number (only input devices have tuners, only output devices have modulators),
  3760. zero out the reserved array and call the VIDIOC_G_FREQUENCY ioctl with a
  3761. pointer to this structure. The driver stores the current frequency in the
  3762. frequency field.
  3763. @param file: File descriptor returned by open().
  3764. @param freq: pointer to struct v4l2_frequency. This will be set to the
  3765. resultant
  3766. frequency in 62.5 khz on success.
  3767. @return On success 0 is returned, else error code.
  3768. @return EINVAL: The tuner index is out of bounds or the value in the type
  3769. field is wrong.
  3770. */
  3771. static int tavarua_vidioc_g_frequency(struct file *file, void *priv,
  3772. struct v4l2_frequency *freq)
  3773. {
  3774. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3775. if (unlikely(radio == NULL)) {
  3776. FMDERR("%s:radio is null", __func__);
  3777. return -EINVAL;
  3778. }
  3779. if (unlikely(freq == NULL)) {
  3780. FMDERR("%s:freq is null", __func__);
  3781. return -EINVAL;
  3782. }
  3783. freq->type = V4L2_TUNER_RADIO;
  3784. return tavarua_get_freq(radio, freq);
  3785. }
  3786. /*=============================================================================
  3787. FUNCTION: tavarua_vidioc_s_frequency
  3788. =============================================================================*/
  3789. /**
  3790. This function is called to set tuner or modulator radio frequency.
  3791. NOTE:
  3792. To change the current tuner or modulator radio frequency applications
  3793. initialize the tuner, type and frequency fields, and the reserved array of
  3794. a struct v4l2_frequency and call the VIDIOC_S_FREQUENCY ioctl with a pointer
  3795. to this structure. When the requested frequency is not possible the driver
  3796. assumes the closest possible value. However VIDIOC_S_FREQUENCY is a
  3797. write-only ioctl, it does not return the actual new frequency.
  3798. @param file: File descriptor returned by open().
  3799. @param freq: pointer to struct v4l2_frequency.
  3800. @return On success 0 is returned, else error code.
  3801. @return EINVAL: The tuner index is out of bounds or the value in the type
  3802. field is wrong.
  3803. */
  3804. static int tavarua_vidioc_s_frequency(struct file *file, void *priv,
  3805. struct v4l2_frequency *freq)
  3806. {
  3807. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3808. int retval = -1;
  3809. struct v4l2_frequency getFreq;
  3810. FMDBG("%s\n", __func__);
  3811. if (unlikely(radio == NULL)) {
  3812. FMDERR("%s:radio is null", __func__);
  3813. return -EINVAL;
  3814. }
  3815. if (unlikely(freq == NULL)) {
  3816. FMDERR("%s:freq is null", __func__);
  3817. return -EINVAL;
  3818. }
  3819. if (freq->type != V4L2_TUNER_RADIO)
  3820. return -EINVAL;
  3821. FMDBG("Calling tavarua_set_freq\n");
  3822. INIT_COMPLETION(radio->sync_req_done);
  3823. retval = tavarua_set_freq(radio, freq->frequency);
  3824. if (retval < 0) {
  3825. printk(KERN_WARNING DRIVER_NAME
  3826. ": set frequency failed with %d\n", retval);
  3827. } else {
  3828. /* Wait for interrupt i.e. complete
  3829. (&radio->sync_req_done); call */
  3830. if (!wait_for_completion_timeout(&radio->sync_req_done,
  3831. msecs_to_jiffies(wait_timeout))) {
  3832. FMDERR("Timeout: No Tune response");
  3833. retval = tavarua_get_freq(radio, &getFreq);
  3834. radio->tune_req = 0;
  3835. if (retval > 0) {
  3836. if (getFreq.frequency == freq->frequency) {
  3837. /** This is success, queut the event*/
  3838. tavarua_q_event(radio,
  3839. TAVARUA_EVT_TUNE_SUCC);
  3840. return 0;
  3841. } else {
  3842. return -EIO;
  3843. }
  3844. }
  3845. }
  3846. }
  3847. radio->tune_req = 0;
  3848. return retval;
  3849. }
  3850. /*=============================================================================
  3851. FUNCTION: tavarua_vidioc_dqbuf
  3852. =============================================================================*/
  3853. /**
  3854. This function is called to exchange a buffer with the driver.
  3855. This is main buffer function, in essense its equivalent to a blocking
  3856. read call.
  3857. Applications call the VIDIOC_DQBUF ioctl to dequeue a filled (capturing) or
  3858. displayed (output) buffer from the driver's outgoing queue. They just set
  3859. the type and memory fields of a struct v4l2_buffer as above, when VIDIOC_DQBUF
  3860. is called with a pointer to this structure the driver fills the remaining
  3861. fields or returns an error code.
  3862. NOTE:
  3863. By default VIDIOC_DQBUF blocks when no buffer is in the outgoing queue.
  3864. When the O_NONBLOCK flag was given to the open() function, VIDIOC_DQBUF
  3865. returns immediately with an EAGAIN error code when no buffer is available.
  3866. @param file: File descriptor returned by open().
  3867. @param buffer: pointer to struct v4l2_buffer.
  3868. @return On success 0 is returned, else error code.
  3869. @return EAGAIN: Non-blocking I/O has been selected using O_NONBLOCK and no
  3870. buffer was in the outgoing queue.
  3871. @return EINVAL: The buffer type is not supported, or the index is out of
  3872. bounds, or no buffers have been allocated yet, or the userptr or length are
  3873. invalid.
  3874. @return ENOMEM: Not enough physical or virtual memory was available to enqueue
  3875. a user pointer buffer.
  3876. @return EIO: VIDIOC_DQBUF failed due to an internal error. Can also indicate
  3877. temporary problems like signal loss. Note the driver might dequeue an (empty)
  3878. buffer despite returning an error, or even stop capturing.
  3879. */
  3880. static int tavarua_vidioc_dqbuf(struct file *file, void *priv,
  3881. struct v4l2_buffer *buffer)
  3882. {
  3883. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3884. enum tavarua_buf_t buf_type = -1;
  3885. unsigned char buf_fifo[STD_BUF_SIZE] = {0};
  3886. struct kfifo *data_fifo = NULL;
  3887. unsigned char *buf = NULL;
  3888. unsigned int len = 0, retval = -1;
  3889. if ((radio == NULL) || (buffer == NULL)) {
  3890. FMDERR("radio/buffer is NULL\n");
  3891. return -ENXIO;
  3892. }
  3893. buf_type = buffer->index;
  3894. buf = (unsigned char *)buffer->m.userptr;
  3895. len = buffer->length;
  3896. FMDBG("%s: requesting buffer %d\n", __func__, buf_type);
  3897. if ((buf_type < TAVARUA_BUF_MAX) && (buf_type >= 0)) {
  3898. data_fifo = &radio->data_buf[buf_type];
  3899. if (buf_type == TAVARUA_BUF_EVENTS) {
  3900. if (wait_event_interruptible(radio->event_queue,
  3901. kfifo_len(data_fifo)) < 0) {
  3902. return -EINTR;
  3903. }
  3904. }
  3905. } else {
  3906. FMDERR("invalid buffer type\n");
  3907. return -EINVAL;
  3908. }
  3909. if (len <= STD_BUF_SIZE) {
  3910. buffer->bytesused = kfifo_out_locked(data_fifo, &buf_fifo[0],
  3911. len, &radio->buf_lock[buf_type]);
  3912. } else {
  3913. FMDERR("kfifo_out_locked can not use len more than 128\n");
  3914. return -EINVAL;
  3915. }
  3916. retval = copy_to_user(buf, &buf_fifo[0], buffer->bytesused);
  3917. if (retval > 0) {
  3918. FMDERR("Failed to copy %d bytes of data\n", retval);
  3919. return -EAGAIN;
  3920. }
  3921. return retval;
  3922. }
  3923. /*=============================================================================
  3924. FUNCTION: tavarua_vidioc_g_fmt_type_private
  3925. =============================================================================*/
  3926. /**
  3927. This function is here to make the v4l2 framework happy.
  3928. We cannot use private buffers without it.
  3929. @param file: File descriptor returned by open().
  3930. @param f: pointer to struct v4l2_format.
  3931. @return On success 0 is returned, else error code.
  3932. @return EINVAL: The tuner index is out of bounds or the value in the type
  3933. field is wrong.
  3934. */
  3935. static int tavarua_vidioc_g_fmt_type_private(struct file *file, void *priv,
  3936. struct v4l2_format *f)
  3937. {
  3938. return 0;
  3939. }
  3940. /*=============================================================================
  3941. FUNCTION: tavarua_vidioc_s_hw_freq_seek
  3942. =============================================================================*/
  3943. /**
  3944. This function is called to perform a hardware frequency seek.
  3945. Start a hardware frequency seek from the current frequency. To do this
  3946. applications initialize the tuner, type, seek_upward and wrap_around fields,
  3947. and zero out the reserved array of a struct v4l2_hw_freq_seek and call the
  3948. VIDIOC_S_HW_FREQ_SEEK ioctl with a pointer to this structure.
  3949. This ioctl is supported if the V4L2_CAP_HW_FREQ_SEEK capability is set.
  3950. @param file: File descriptor returned by open().
  3951. @param seek: pointer to struct v4l2_hw_freq_seek.
  3952. @return On success 0 is returned, else error code.
  3953. @return EINVAL: The tuner index is out of bounds or the value in the type
  3954. field is wrong.
  3955. @return EAGAIN: The ioctl timed-out. Try again.
  3956. */
  3957. static int tavarua_vidioc_s_hw_freq_seek(struct file *file, void *priv,
  3958. struct v4l2_hw_freq_seek *seek)
  3959. {
  3960. struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
  3961. int dir;
  3962. if (unlikely(radio == NULL)) {
  3963. FMDERR("%s:radio is null", __func__);
  3964. return -EINVAL;
  3965. }
  3966. if (unlikely(seek == NULL)) {
  3967. FMDERR("%s:seek is null", __func__);
  3968. return -EINVAL;
  3969. }
  3970. if (seek->seek_upward)
  3971. dir = SRCH_DIR_UP;
  3972. else
  3973. dir = SRCH_DIR_DOWN;
  3974. FMDBG("starting search\n");
  3975. return tavarua_search(radio, CTRL_ON, dir);
  3976. }
  3977. /*
  3978. * tavarua_viddev_tamples - video device interface
  3979. */
  3980. static const struct v4l2_ioctl_ops tavarua_ioctl_ops = {
  3981. .vidioc_querycap = tavarua_vidioc_querycap,
  3982. .vidioc_queryctrl = tavarua_vidioc_queryctrl,
  3983. .vidioc_g_ctrl = tavarua_vidioc_g_ctrl,
  3984. .vidioc_s_ctrl = tavarua_vidioc_s_ctrl,
  3985. .vidioc_g_tuner = tavarua_vidioc_g_tuner,
  3986. .vidioc_s_tuner = tavarua_vidioc_s_tuner,
  3987. .vidioc_g_frequency = tavarua_vidioc_g_frequency,
  3988. .vidioc_s_frequency = tavarua_vidioc_s_frequency,
  3989. .vidioc_s_hw_freq_seek = tavarua_vidioc_s_hw_freq_seek,
  3990. .vidioc_dqbuf = tavarua_vidioc_dqbuf,
  3991. .vidioc_g_fmt_type_private = tavarua_vidioc_g_fmt_type_private,
  3992. .vidioc_s_ext_ctrls = tavarua_vidioc_s_ext_ctrls,
  3993. };
  3994. static struct video_device tavarua_viddev_template = {
  3995. .fops = &tavarua_fops,
  3996. .ioctl_ops = &tavarua_ioctl_ops,
  3997. .name = DRIVER_NAME,
  3998. .release = video_device_release,
  3999. };
  4000. /*==============================================================
  4001. FUNCTION: FmQSocCom_EnableInterrupts
  4002. ==============================================================*/
  4003. /**
  4004. This function enable interrupts.
  4005. @param radio: structure pointer passed by client.
  4006. @param state: FM radio state (receiver/transmitter/off/reset).
  4007. @return => 0 if successful.
  4008. @return < 0 if failure.
  4009. */
  4010. static int tavarua_setup_interrupts(struct tavarua_device *radio,
  4011. enum radio_state_t state)
  4012. {
  4013. int retval;
  4014. unsigned char int_ctrl[XFR_REG_NUM];
  4015. if (unlikely(radio == NULL)) {
  4016. FMDERR("%s:radio is null", __func__);
  4017. return -EINVAL;
  4018. }
  4019. if (!radio->lp_mode)
  4020. return 0;
  4021. int_ctrl[STATUS_REG1] = READY | TUNE | SEARCH | SCANNEXT |
  4022. SIGNAL | INTF | SYNC | AUDIO;
  4023. if (state == FM_RECV)
  4024. int_ctrl[STATUS_REG2] = RDSDAT | RDSRT | RDSPS | RDSAF;
  4025. else
  4026. int_ctrl[STATUS_REG2] = TXRDSDAT | TXRDSDONE;
  4027. int_ctrl[STATUS_REG3] = TRANSFER | ERROR;
  4028. /* use xfr for interrupt setup */
  4029. if (radio->chipID == MARIMBA_2_1 || radio->chipID == BAHAMA_1_0
  4030. || radio->chipID == BAHAMA_2_0 || radio->chipID == BAHAMA_2_1) {
  4031. FMDBG("Setting interrupts\n");
  4032. retval = sync_write_xfr(radio, INT_CTRL, int_ctrl);
  4033. /* use register write to setup interrupts */
  4034. } else {
  4035. retval = tavarua_write_register(radio,
  4036. STATUS_REG1, int_ctrl[STATUS_REG1]);
  4037. if (retval < 0)
  4038. return retval;
  4039. retval = tavarua_write_register(radio,
  4040. STATUS_REG2, int_ctrl[STATUS_REG2]);
  4041. if (retval < 0)
  4042. return retval;
  4043. retval = tavarua_write_register(radio,
  4044. STATUS_REG3, int_ctrl[STATUS_REG3]);
  4045. if (retval < 0)
  4046. return retval;
  4047. }
  4048. radio->lp_mode = 0;
  4049. /* tavarua_handle_interrupts force reads all the interrupt status
  4050. * registers and it is not valid for MBA 2.1
  4051. */
  4052. if ((radio->chipID != MARIMBA_2_1) && (radio->chipID != BAHAMA_1_0)
  4053. && (radio->chipID != BAHAMA_2_0)
  4054. && (radio->chipID != BAHAMA_2_1))
  4055. tavarua_handle_interrupts(radio);
  4056. return retval;
  4057. }
  4058. /*==============================================================
  4059. FUNCTION: tavarua_disable_interrupts
  4060. ==============================================================*/
  4061. /**
  4062. This function disables interrupts.
  4063. @param radio: structure pointer passed by client.
  4064. @return => 0 if successful.
  4065. @return < 0 if failure.
  4066. */
  4067. static int tavarua_disable_interrupts(struct tavarua_device *radio)
  4068. {
  4069. unsigned char lpm_buf[XFR_REG_NUM];
  4070. int retval;
  4071. if (unlikely(radio == NULL)) {
  4072. FMDERR("%s:radio is null", __func__);
  4073. return -EINVAL;
  4074. }
  4075. if (radio->lp_mode)
  4076. return 0;
  4077. FMDBG("%s\n", __func__);
  4078. /* In Low power mode, disable all the interrupts that are not being
  4079. waited by the Application */
  4080. lpm_buf[STATUS_REG1] = TUNE | SEARCH | SCANNEXT;
  4081. lpm_buf[STATUS_REG2] = 0x00;
  4082. lpm_buf[STATUS_REG3] = TRANSFER;
  4083. /* use xfr for interrupt setup */
  4084. wait_timeout = 100;
  4085. if (radio->chipID == MARIMBA_2_1 || radio->chipID == BAHAMA_1_0
  4086. || radio->chipID == BAHAMA_2_0 || radio->chipID == BAHAMA_2_1)
  4087. retval = sync_write_xfr(radio, INT_CTRL, lpm_buf);
  4088. /* use register write to setup interrupts */
  4089. else
  4090. retval = tavarua_write_registers(radio, STATUS_REG1, lpm_buf,
  4091. ARRAY_SIZE(lpm_buf));
  4092. /*INT_CTL writes may fail with TIME_OUT as all the
  4093. interrupts have been disabled
  4094. */
  4095. if (retval > -1 || retval == -ETIME) {
  4096. radio->lp_mode = 1;
  4097. /*Consider timeout as a valid case here*/
  4098. retval = 0;
  4099. }
  4100. wait_timeout = WAIT_TIMEOUT;
  4101. return retval;
  4102. }
  4103. /*==============================================================
  4104. FUNCTION: tavarua_start
  4105. ==============================================================*/
  4106. /**
  4107. Starts/enables the device (FM radio).
  4108. @param radio: structure pointer passed by client.
  4109. @param state: FM radio state (receiver/transmitter/off/reset).
  4110. @return On success 0 is returned, else error code.
  4111. */
  4112. static int tavarua_start(struct tavarua_device *radio,
  4113. enum radio_state_t state)
  4114. {
  4115. int retval;
  4116. FMDBG("%s <%d>\n", __func__, state);
  4117. if (unlikely(radio == NULL)) {
  4118. FMDERR("%s:radio is null", __func__);
  4119. return -EINVAL;
  4120. }
  4121. /* set geographic region */
  4122. radio->region_params.region = TAVARUA_REGION_US;
  4123. /* set radio mode */
  4124. retval = tavarua_write_register(radio, RDCTRL, state);
  4125. if (retval < 0)
  4126. return retval;
  4127. /* wait for radio to init */
  4128. msleep(RADIO_INIT_TIME);
  4129. /* enable interrupts */
  4130. tavarua_setup_interrupts(radio, state);
  4131. /* default region is US */
  4132. radio->region_params.band_low = US_LOW_BAND * FREQ_MUL;
  4133. radio->region_params.band_high = US_HIGH_BAND * FREQ_MUL;
  4134. return 0;
  4135. }
  4136. /*==============================================================
  4137. FUNCTION: tavarua_suspend
  4138. ==============================================================*/
  4139. /**
  4140. Save state and stop all devices in system.
  4141. @param pdev: platform device to be suspended.
  4142. @param state: Power state to put each device in.
  4143. @return On success 0 is returned, else error code.
  4144. */
  4145. static int tavarua_suspend(struct platform_device *pdev, pm_message_t state)
  4146. {
  4147. struct tavarua_device *radio = platform_get_drvdata(pdev);
  4148. int retval;
  4149. int users = 0;
  4150. printk(KERN_INFO DRIVER_NAME "%s: radio suspend\n\n", __func__);
  4151. if (unlikely(radio == NULL)) {
  4152. FMDERR("%s:radio is null", __func__);
  4153. return -EINVAL;
  4154. }
  4155. if (radio) {
  4156. users = atomic_read(&radio->users);
  4157. if (!users) {
  4158. retval = tavarua_disable_interrupts(radio);
  4159. if (retval < 0) {
  4160. printk(KERN_INFO DRIVER_NAME
  4161. "tavarua_suspend error %d\n", retval);
  4162. return -EIO;
  4163. }
  4164. }
  4165. }
  4166. return 0;
  4167. }
  4168. /*==============================================================
  4169. FUNCTION: tavarua_resume
  4170. ==============================================================*/
  4171. /**
  4172. Restore state of each device in system.
  4173. @param pdev: platform device to be resumed.
  4174. @return On success 0 is returned, else error code.
  4175. */
  4176. static int tavarua_resume(struct platform_device *pdev)
  4177. {
  4178. struct tavarua_device *radio = platform_get_drvdata(pdev);
  4179. int retval;
  4180. int users = 0;
  4181. printk(KERN_INFO DRIVER_NAME "%s: radio resume\n\n", __func__);
  4182. if (unlikely(radio == NULL)) {
  4183. FMDERR("%s:radio is null", __func__);
  4184. return -EINVAL;
  4185. }
  4186. if (radio) {
  4187. users = atomic_read(&radio->users);
  4188. if (!users) {
  4189. retval = tavarua_setup_interrupts(radio,
  4190. (radio->registers[RDCTRL] & 0x03));
  4191. if (retval < 0) {
  4192. FMDERR("Fails to write RDCTRL");
  4193. msleep(TAVARUA_DELAY);
  4194. retval = tavarua_setup_interrupts(radio,
  4195. (radio->registers[RDCTRL] & 0x03));
  4196. if (retval < 0) {
  4197. FMDERR("Error in tavarua_resume %d\n",
  4198. retval);
  4199. return -EIO;
  4200. }
  4201. }
  4202. }
  4203. }
  4204. return 0;
  4205. }
  4206. /*==============================================================
  4207. FUNCTION: tavarua_set_audio_path
  4208. ==============================================================*/
  4209. /**
  4210. This function will configure the audio path to and from the
  4211. FM core.
  4212. This interface is expected to be called from the multimedia
  4213. driver's thread. This interface should only be called when
  4214. the FM hardware is enabled. If the FM hardware is not
  4215. currently enabled, this interface will return an error.
  4216. @param digital_on: Digital audio from the FM core should be enabled/disbled.
  4217. @param analog_on: Analog audio from the FM core should be enabled/disbled.
  4218. @return On success 0 is returned, else error code.
  4219. */
  4220. int tavarua_set_audio_path(int digital_on, int analog_on)
  4221. {
  4222. struct tavarua_device *radio = private_data;
  4223. int rx_on = radio->registers[RDCTRL] & FM_RECV;
  4224. int retval = 0;
  4225. if (unlikely(radio == NULL)) {
  4226. FMDERR("%s:radio is null", __func__);
  4227. return -EINVAL;
  4228. }
  4229. /* RX */
  4230. FMDBG("%s: digital: %d analog: %d\n", __func__, digital_on, analog_on);
  4231. if ((radio->pdata != NULL) && (radio->pdata->config_i2s_gpio != NULL)) {
  4232. if (digital_on) {
  4233. retval = radio->pdata->config_i2s_gpio(FM_I2S_ON);
  4234. if (retval) {
  4235. pr_err("%s: config_i2s_gpio failed\n",
  4236. __func__);
  4237. }
  4238. } else {
  4239. retval = radio->pdata->config_i2s_gpio(FM_I2S_OFF);
  4240. if (retval) {
  4241. pr_err("%s: config_i2s_gpio failed\n",
  4242. __func__);
  4243. }
  4244. }
  4245. }
  4246. SET_REG_FIELD(radio->registers[AUDIOCTRL],
  4247. ((rx_on && analog_on) ? 1 : 0),
  4248. AUDIORX_ANALOG_OFFSET,
  4249. AUDIORX_ANALOG_MASK);
  4250. SET_REG_FIELD(radio->registers[AUDIOCTRL],
  4251. ((rx_on && digital_on) ? 1 : 0),
  4252. AUDIORX_DIGITAL_OFFSET,
  4253. AUDIORX_DIGITAL_MASK);
  4254. SET_REG_FIELD(radio->registers[AUDIOCTRL],
  4255. (rx_on ? 0 : 1),
  4256. AUDIOTX_OFFSET,
  4257. AUDIOTX_MASK);
  4258. /*
  4259. I2S Master/Slave configuration:
  4260. Setting the FM SoC as I2S Master/Slave
  4261. 'false' - FM SoC is I2S Slave
  4262. 'true' - FM SoC is I2S Master
  4263. We get this infomation from the respective target's board file :
  4264. MSM7x30 - FM SoC is I2S Slave
  4265. MSM8x60 - FM SoC is I2S Slave
  4266. MSM7x27A - FM SoC is I2S Master
  4267. */
  4268. if (!radio->pdata->is_fm_soc_i2s_master) {
  4269. FMDBG("FM SoC is I2S Slave\n");
  4270. SET_REG_FIELD(radio->registers[AUDIOCTRL],
  4271. (0),
  4272. I2SCTRL_OFFSET,
  4273. I2SCTRL_MASK);
  4274. } else {
  4275. FMDBG("FM SoC is I2S Master\n");
  4276. SET_REG_FIELD(radio->registers[AUDIOCTRL],
  4277. (1),
  4278. I2SCTRL_OFFSET,
  4279. I2SCTRL_MASK);
  4280. }
  4281. FMDBG("%s: %x\n", __func__, radio->registers[AUDIOCTRL]);
  4282. return tavarua_write_register(radio, AUDIOCTRL,
  4283. radio->registers[AUDIOCTRL]);
  4284. }
  4285. /*==============================================================
  4286. FUNCTION: tavarua_probe
  4287. ==============================================================*/
  4288. /**
  4289. Once called this functions initiates, allocates resources and registers video
  4290. tuner device with the v4l2 framework.
  4291. NOTE:
  4292. probe() should verify that the specified device hardware
  4293. actually exists; sometimes platform setup code can't be sure. The probing
  4294. can use device resources, including clocks, and device platform_data.
  4295. @param pdev: platform device to be probed.
  4296. @return On success 0 is returned, else error code.
  4297. -ENOMEM in low memory cases
  4298. */
  4299. static int __init tavarua_probe(struct platform_device *pdev)
  4300. {
  4301. struct marimba_fm_platform_data *tavarua_pdata;
  4302. struct tavarua_device *radio;
  4303. int retval = 0;
  4304. int i = 0, j = 0;
  4305. FMDBG("%s: probe called\n", __func__);
  4306. if (unlikely(pdev == NULL)) {
  4307. FMDERR("%s:pdev is null", __func__);
  4308. return -EINVAL;
  4309. }
  4310. /* private data allocation */
  4311. radio = kzalloc(sizeof(struct tavarua_device), GFP_KERNEL);
  4312. if (!radio) {
  4313. retval = -ENOMEM;
  4314. goto err_initial;
  4315. }
  4316. radio->marimba = platform_get_drvdata(pdev);
  4317. tavarua_pdata = pdev->dev.platform_data;
  4318. radio->pdata = tavarua_pdata;
  4319. radio->dev = &pdev->dev;
  4320. radio->wqueue = NULL;
  4321. platform_set_drvdata(pdev, radio);
  4322. /* video device allocation */
  4323. radio->videodev = video_device_alloc();
  4324. if (!radio->videodev)
  4325. goto err_radio;
  4326. /* initial configuration */
  4327. memcpy(radio->videodev, &tavarua_viddev_template,
  4328. sizeof(tavarua_viddev_template));
  4329. /*allocate internal buffers for decoded rds and event buffer*/
  4330. for (i = 0; i < TAVARUA_BUF_MAX; i++) {
  4331. int kfifo_alloc_rc=0;
  4332. spin_lock_init(&radio->buf_lock[i]);
  4333. if (i == TAVARUA_BUF_RAW_RDS)
  4334. kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
  4335. rds_buf*3, GFP_KERNEL);
  4336. else if (i == TAVARUA_BUF_RT_RDS)
  4337. kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
  4338. STD_BUF_SIZE * 2, GFP_KERNEL);
  4339. else
  4340. kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
  4341. STD_BUF_SIZE, GFP_KERNEL);
  4342. if (kfifo_alloc_rc!=0) {
  4343. printk(KERN_ERR "%s: failed allocating buffers %d\n",
  4344. __func__, kfifo_alloc_rc);
  4345. retval = -ENOMEM;
  4346. goto err_all;
  4347. }
  4348. }
  4349. /* initializing the device count */
  4350. atomic_set(&radio->users, 1);
  4351. radio->xfr_in_progress = 0;
  4352. radio->xfr_bytes_left = 0;
  4353. for (j = 0; j < TAVARUA_XFR_MAX; j++)
  4354. radio->pending_xfrs[j] = 0;
  4355. /* init transmit data */
  4356. radio->tx_mode = TAVARUA_TX_RT;
  4357. /* Init RT and PS Tx datas*/
  4358. radio->pty = 0;
  4359. radio->pi = 0;
  4360. radio->ps_repeatcount = 0;
  4361. /* init search params */
  4362. radio->srch_params.srch_pty = 0;
  4363. radio->srch_params.srch_pi = 0;
  4364. radio->srch_params.preset_num = 0;
  4365. radio->srch_params.get_list = 0;
  4366. /* radio initializes to low power mode */
  4367. radio->lp_mode = 1;
  4368. radio->handle_irq = 1;
  4369. /* init lock */
  4370. mutex_init(&radio->lock);
  4371. /* init completion flags */
  4372. init_completion(&radio->sync_xfr_start);
  4373. init_completion(&radio->sync_req_done);
  4374. radio->tune_req = 0;
  4375. /* initialize wait queue for event read */
  4376. init_waitqueue_head(&radio->event_queue);
  4377. /* initialize wait queue for raw rds read */
  4378. init_waitqueue_head(&radio->read_queue);
  4379. video_set_drvdata(radio->videodev, radio);
  4380. /*Start the worker thread for event handling and register read_int_stat
  4381. as worker function*/
  4382. radio->wqueue = create_singlethread_workqueue("kfmradio");
  4383. if (!radio->wqueue) {
  4384. retval = -ENOMEM;
  4385. goto err_all;
  4386. }
  4387. /* register video device */
  4388. retval = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
  4389. if (retval != 0) {
  4390. printk(KERN_WARNING DRIVER_NAME
  4391. ": Could not register video device\n");
  4392. goto err_all;
  4393. }
  4394. private_data = radio;
  4395. return 0;
  4396. err_all:
  4397. video_device_release(radio->videodev);
  4398. if (radio->wqueue)
  4399. destroy_workqueue(radio->wqueue);
  4400. for (i--; i >= 0; i--) {
  4401. kfifo_free(&radio->data_buf[i]);
  4402. }
  4403. err_radio:
  4404. kfree(radio);
  4405. err_initial:
  4406. return retval;
  4407. }
  4408. /*==============================================================
  4409. FUNCTION: tavarua_remove
  4410. ==============================================================*/
  4411. /**
  4412. Removes the device.
  4413. @param pdev: platform device to be removed.
  4414. @return On success 0 is returned, else error code.
  4415. */
  4416. static int __devexit tavarua_remove(struct platform_device *pdev)
  4417. {
  4418. int i;
  4419. struct tavarua_device *radio = platform_get_drvdata(pdev);
  4420. if (unlikely(radio == NULL)) {
  4421. FMDERR("%s:radio is null", __func__);
  4422. return -EINVAL;
  4423. }
  4424. /* disable irq */
  4425. tavarua_disable_irq(radio);
  4426. destroy_workqueue(radio->wqueue);
  4427. video_unregister_device(radio->videodev);
  4428. /* free internal buffers */
  4429. for (i = 0; i < TAVARUA_BUF_MAX; i++)
  4430. kfifo_free(&radio->data_buf[i]);
  4431. /* free state struct */
  4432. kfree(radio);
  4433. platform_set_drvdata(pdev, NULL);
  4434. return 0;
  4435. }
  4436. /*
  4437. Platform drivers follow the standard driver model convention, where
  4438. discovery/enumeration is handled outside the drivers, and drivers
  4439. provide probe() and remove() methods. They support power management
  4440. and shutdown notifications using the standard conventions.
  4441. */
  4442. static struct platform_driver tavarua_driver = {
  4443. .driver = {
  4444. .owner = THIS_MODULE,
  4445. .name = "marimba_fm",
  4446. },
  4447. .remove = __devexit_p(tavarua_remove),
  4448. .suspend = tavarua_suspend,
  4449. .resume = tavarua_resume,
  4450. }; /* platform device we're adding */
  4451. /*************************************************************************
  4452. * Module Interface
  4453. ************************************************************************/
  4454. /*==============================================================
  4455. FUNCTION: radio_module_init
  4456. ==============================================================*/
  4457. /**
  4458. Module entry - add a platform-level device.
  4459. @return Returns zero if the driver registered and bound to a device, else
  4460. returns a negative error code when the driver not registered.
  4461. */
  4462. static int __init radio_module_init(void)
  4463. {
  4464. printk(KERN_INFO DRIVER_DESC ", Version " DRIVER_VERSION "\n");
  4465. return platform_driver_probe(&tavarua_driver, tavarua_probe);
  4466. }
  4467. /*==============================================================
  4468. FUNCTION: radio_module_exit
  4469. ==============================================================*/
  4470. /**
  4471. Module exit - removes a platform-level device.
  4472. NOTE:
  4473. Note that this function will also release all memory- and port-based
  4474. resources owned by the device (dev->resource).
  4475. @return none.
  4476. */
  4477. static void __exit radio_module_exit(void)
  4478. {
  4479. platform_driver_unregister(&tavarua_driver);
  4480. }
  4481. MODULE_LICENSE("GPL v2");
  4482. MODULE_AUTHOR(DRIVER_AUTHOR);
  4483. MODULE_DESCRIPTION(DRIVER_DESC);
  4484. MODULE_VERSION(DRIVER_VERSION);
  4485. module_init(radio_module_init);
  4486. module_exit(radio_module_exit);