12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179 |
- /*
- *
- * $Id$
- *
- * Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
- #include <linux/errno.h>
- #include <linux/string.h>
- #include <linux/slab.h>
- #include <linux/firmware.h>
- #include <linux/videodev2.h>
- #include <media/v4l2-common.h>
- #include <asm/semaphore.h>
- #include "pvrusb2.h"
- #include "pvrusb2-std.h"
- #include "pvrusb2-util.h"
- #include "pvrusb2-hdw.h"
- #include "pvrusb2-i2c-core.h"
- #include "pvrusb2-tuner.h"
- #include "pvrusb2-eeprom.h"
- #include "pvrusb2-hdw-internal.h"
- #include "pvrusb2-encoder.h"
- #include "pvrusb2-debug.h"
- struct usb_device_id pvr2_device_table[] = {
- [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
- [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
- { }
- };
- MODULE_DEVICE_TABLE(usb, pvr2_device_table);
- static const char *pvr2_device_names[] = {
- [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",
- [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",
- };
- struct pvr2_string_table {
- const char **lst;
- unsigned int cnt;
- };
- // Names of other client modules to request for 24xxx model hardware
- static const char *pvr2_client_24xxx[] = {
- "cx25840",
- "tuner",
- "wm8775",
- };
- // Names of other client modules to request for 29xxx model hardware
- static const char *pvr2_client_29xxx[] = {
- "msp3400",
- "saa7115",
- "tuner",
- };
- static struct pvr2_string_table pvr2_client_lists[] = {
- [PVR2_HDW_TYPE_29XXX] = {
- pvr2_client_29xxx,
- sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
- },
- [PVR2_HDW_TYPE_24XXX] = {
- pvr2_client_24xxx,
- sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
- },
- };
- static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
- static DECLARE_MUTEX(pvr2_unit_sem);
- static int ctlchg = 0;
- static int initusbreset = 1;
- static int procreload = 0;
- static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
- static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
- static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
- static int init_pause_msec = 0;
- module_param(ctlchg, int, S_IRUGO|S_IWUSR);
- MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
- module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
- MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
- module_param(initusbreset, int, S_IRUGO|S_IWUSR);
- MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");
- module_param(procreload, int, S_IRUGO|S_IWUSR);
- MODULE_PARM_DESC(procreload,
- "Attempt init failure recovery with firmware reload");
- module_param_array(tuner, int, NULL, 0444);
- MODULE_PARM_DESC(tuner,"specify installed tuner type");
- module_param_array(video_std, int, NULL, 0444);
- MODULE_PARM_DESC(video_std,"specify initial video standard");
- module_param_array(tolerance, int, NULL, 0444);
- MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
- #define PVR2_CTL_WRITE_ENDPOINT 0x01
- #define PVR2_CTL_READ_ENDPOINT 0x81
- #define PVR2_GPIO_IN 0x9008
- #define PVR2_GPIO_OUT 0x900c
- #define PVR2_GPIO_DIR 0x9020
- #define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__)
- #define PVR2_FIRMWARE_ENDPOINT 0x02
- /* size of a firmware chunk */
- #define FIRMWARE_CHUNK_SIZE 0x2000
- /* Define the list of additional controls we'll dynamically construct based
- on query of the cx2341x module. */
- struct pvr2_mpeg_ids {
- const char *strid;
- int id;
- };
- static const struct pvr2_mpeg_ids mpeg_ids[] = {
- {
- .strid = "audio_layer",
- .id = V4L2_CID_MPEG_AUDIO_ENCODING,
- },{
- .strid = "audio_bitrate",
- .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE,
- },{
- /* Already using audio_mode elsewhere :-( */
- .strid = "mpeg_audio_mode",
- .id = V4L2_CID_MPEG_AUDIO_MODE,
- },{
- .strid = "mpeg_audio_mode_extension",
- .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
- },{
- .strid = "audio_emphasis",
- .id = V4L2_CID_MPEG_AUDIO_EMPHASIS,
- },{
- .strid = "audio_crc",
- .id = V4L2_CID_MPEG_AUDIO_CRC,
- },{
- .strid = "video_aspect",
- .id = V4L2_CID_MPEG_VIDEO_ASPECT,
- },{
- .strid = "video_b_frames",
- .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
- },{
- .strid = "video_gop_size",
- .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
- },{
- .strid = "video_gop_closure",
- .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
- },{
- .strid = "video_pulldown",
- .id = V4L2_CID_MPEG_VIDEO_PULLDOWN,
- },{
- .strid = "video_bitrate_mode",
- .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
- },{
- .strid = "video_bitrate",
- .id = V4L2_CID_MPEG_VIDEO_BITRATE,
- },{
- .strid = "video_bitrate_peak",
- .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
- },{
- .strid = "video_temporal_decimation",
- .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
- },{
- .strid = "stream_type",
- .id = V4L2_CID_MPEG_STREAM_TYPE,
- },{
- .strid = "video_spatial_filter_mode",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
- },{
- .strid = "video_spatial_filter",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
- },{
- .strid = "video_luma_spatial_filter_type",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
- },{
- .strid = "video_chroma_spatial_filter_type",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
- },{
- .strid = "video_temporal_filter_mode",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
- },{
- .strid = "video_temporal_filter",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
- },{
- .strid = "video_median_filter_type",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
- },{
- .strid = "video_luma_median_filter_top",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
- },{
- .strid = "video_luma_median_filter_bottom",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
- },{
- .strid = "video_chroma_median_filter_top",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
- },{
- .strid = "video_chroma_median_filter_bottom",
- .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
- }
- };
- #define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
- static const char *control_values_srate[] = {
- [V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100] = "44.1 kHz",
- [V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000] = "48 kHz",
- [V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000] = "32 kHz",
- };
- static const char *control_values_input[] = {
- [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/
- [PVR2_CVAL_INPUT_RADIO] = "radio",
- [PVR2_CVAL_INPUT_SVIDEO] = "s-video",
- [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
- };
- static const char *control_values_audiomode[] = {
- [V4L2_TUNER_MODE_MONO] = "Mono",
- [V4L2_TUNER_MODE_STEREO] = "Stereo",
- [V4L2_TUNER_MODE_LANG1] = "Lang1",
- [V4L2_TUNER_MODE_LANG2] = "Lang2",
- [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2",
- };
- static const char *control_values_hsm[] = {
- [PVR2_CVAL_HSM_FAIL] = "Fail",
- [PVR2_CVAL_HSM_HIGH] = "High",
- [PVR2_CVAL_HSM_FULL] = "Full",
- };
- static const char *control_values_subsystem[] = {
- [PVR2_SUBSYS_B_ENC_FIRMWARE] = "enc_firmware",
- [PVR2_SUBSYS_B_ENC_CFG] = "enc_config",
- [PVR2_SUBSYS_B_DIGITIZER_RUN] = "digitizer_run",
- [PVR2_SUBSYS_B_USBSTREAM_RUN] = "usbstream_run",
- [PVR2_SUBSYS_B_ENC_RUN] = "enc_run",
- };
- static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
- static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
- static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
- static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw);
- static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
- static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
- static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw);
- static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
- unsigned long msk,
- unsigned long val);
- static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
- unsigned long msk,
- unsigned long val);
- static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
- unsigned int timeout,int probe_fl,
- void *write_data,unsigned int write_len,
- void *read_data,unsigned int read_len);
- static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res);
- static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res);
- static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
- *vp = hdw->freqTable[hdw->freqProgSlot-1];
- } else {
- *vp = 0;
- }
- return 0;
- }
- static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
- hdw->freqTable[hdw->freqProgSlot-1] = v;
- }
- return 0;
- }
- static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->freqProgSlot;
- return 0;
- }
- static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- if ((v >= 0) && (v <= FREQTABLE_SIZE)) {
- hdw->freqProgSlot = v;
- }
- return 0;
- }
- static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->freqSlot;
- return 0;
- }
- static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- unsigned freq = 0;
- struct pvr2_hdw *hdw = cptr->hdw;
- hdw->freqSlot = v;
- if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) {
- freq = hdw->freqTable[hdw->freqSlot-1];
- }
- if (freq && (freq != hdw->freqVal)) {
- hdw->freqVal = freq;
- hdw->freqDirty = !0;
- }
- return 0;
- }
- static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->freqVal;
- return 0;
- }
- static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr)
- {
- return cptr->hdw->freqDirty != 0;
- }
- static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
- {
- cptr->hdw->freqDirty = 0;
- }
- static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- hdw->freqVal = v;
- hdw->freqDirty = !0;
- hdw->freqSlot = 0;
- return 0;
- }
- static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp)
- {
- /* If we're dealing with a 24xxx device, force the horizontal
- maximum to be 720 no matter what, since we can't get the device
- to work properly with any other value. Otherwise just return
- the normal value. */
- *vp = cptr->info->def.type_int.max_value;
- if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
- return 0;
- }
- static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp)
- {
- /* If we're dealing with a 24xxx device, force the horizontal
- minimum to be 720 no matter what, since we can't get the device
- to work properly with any other value. Otherwise just return
- the normal value. */
- *vp = cptr->info->def.type_int.min_value;
- if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720;
- return 0;
- }
- static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
- {
- /* Actual maximum depends on the video standard in effect. */
- if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) {
- *vp = 480;
- } else {
- *vp = 576;
- }
- return 0;
- }
- static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
- {
- /* Actual minimum depends on device type. */
- if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
- *vp = 75;
- } else {
- *vp = 17;
- }
- return 0;
- }
- static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
- {
- return cptr->hdw->enc_stale != 0;
- }
- static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr)
- {
- cptr->hdw->enc_stale = 0;
- }
- static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
- {
- int ret;
- struct v4l2_ext_controls cs;
- struct v4l2_ext_control c1;
- memset(&cs,0,sizeof(cs));
- memset(&c1,0,sizeof(c1));
- cs.controls = &c1;
- cs.count = 1;
- c1.id = cptr->info->v4l_id;
- ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
- VIDIOC_G_EXT_CTRLS);
- if (ret) return ret;
- *vp = c1.value;
- return 0;
- }
- static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- int ret;
- struct v4l2_ext_controls cs;
- struct v4l2_ext_control c1;
- memset(&cs,0,sizeof(cs));
- memset(&c1,0,sizeof(c1));
- cs.controls = &c1;
- cs.count = 1;
- c1.id = cptr->info->v4l_id;
- c1.value = v;
- ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
- VIDIOC_S_EXT_CTRLS);
- if (ret) return ret;
- cptr->hdw->enc_stale = !0;
- return 0;
- }
- static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
- {
- struct v4l2_queryctrl qctrl;
- struct pvr2_ctl_info *info;
- qctrl.id = cptr->info->v4l_id;
- cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);
- /* Strip out the const so we can adjust a function pointer. It's
- OK to do this here because we know this is a dynamically created
- control, so the underlying storage for the info pointer is (a)
- private to us, and (b) not in read-only storage. Either we do
- this or we significantly complicate the underlying control
- implementation. */
- info = (struct pvr2_ctl_info *)(cptr->info);
- if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
- if (info->set_value) {
- info->set_value = NULL;
- }
- } else {
- if (!(info->set_value)) {
- info->set_value = ctrl_cx2341x_set;
- }
- }
- return qctrl.flags;
- }
- static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->flag_streaming_enabled;
- return 0;
- }
- static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp)
- {
- int result = pvr2_hdw_is_hsm(cptr->hdw);
- *vp = PVR2_CVAL_HSM_FULL;
- if (result < 0) *vp = PVR2_CVAL_HSM_FAIL;
- if (result) *vp = PVR2_CVAL_HSM_HIGH;
- return 0;
- }
- static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->std_mask_avail;
- return 0;
- }
- static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- v4l2_std_id ns;
- ns = hdw->std_mask_avail;
- ns = (ns & ~m) | (v & m);
- if (ns == hdw->std_mask_avail) return 0;
- hdw->std_mask_avail = ns;
- pvr2_hdw_internal_set_std_avail(hdw);
- pvr2_hdw_internal_find_stdenum(hdw);
- return 0;
- }
- static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val,
- char *bufPtr,unsigned int bufSize,
- unsigned int *len)
- {
- *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val);
- return 0;
- }
- static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr,
- const char *bufPtr,unsigned int bufSize,
- int *mskp,int *valp)
- {
- int ret;
- v4l2_std_id id;
- ret = pvr2_std_str_to_id(&id,bufPtr,bufSize);
- if (ret < 0) return ret;
- if (mskp) *mskp = id;
- if (valp) *valp = id;
- return 0;
- }
- static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->std_mask_cur;
- return 0;
- }
- static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- v4l2_std_id ns;
- ns = hdw->std_mask_cur;
- ns = (ns & ~m) | (v & m);
- if (ns == hdw->std_mask_cur) return 0;
- hdw->std_mask_cur = ns;
- hdw->std_dirty = !0;
- pvr2_hdw_internal_find_stdenum(hdw);
- return 0;
- }
- static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr)
- {
- return cptr->hdw->std_dirty != 0;
- }
- static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
- {
- cptr->hdw->std_dirty = 0;
- }
- static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
- PVR2_SIGNAL_OK) ? 1 : 0);
- return 0;
- }
- static int ctrl_subsys_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->subsys_enabled_mask;
- return 0;
- }
- static int ctrl_subsys_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,m,v);
- return 0;
- }
- static int ctrl_subsys_stream_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->subsys_stream_mask;
- return 0;
- }
- static int ctrl_subsys_stream_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,m,v);
- return 0;
- }
- static int ctrl_stdenumcur_set(struct pvr2_ctrl *cptr,int m,int v)
- {
- struct pvr2_hdw *hdw = cptr->hdw;
- if (v < 0) return -EINVAL;
- if (v > hdw->std_enum_cnt) return -EINVAL;
- hdw->std_enum_cur = v;
- if (!v) return 0;
- v--;
- if (hdw->std_mask_cur == hdw->std_defs[v].id) return 0;
- hdw->std_mask_cur = hdw->std_defs[v].id;
- hdw->std_dirty = !0;
- return 0;
- }
- static int ctrl_stdenumcur_get(struct pvr2_ctrl *cptr,int *vp)
- {
- *vp = cptr->hdw->std_enum_cur;
- return 0;
- }
- static int ctrl_stdenumcur_is_dirty(struct pvr2_ctrl *cptr)
- {
- return cptr->hdw->std_dirty != 0;
- }
- static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr)
- {
- cptr->hdw->std_dirty = 0;
- }
- #define DEFINT(vmin,vmax) \
- .type = pvr2_ctl_int, \
- .def.type_int.min_value = vmin, \
- .def.type_int.max_value = vmax
- #define DEFENUM(tab) \
- .type = pvr2_ctl_enum, \
- .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
- .def.type_enum.value_names = tab
- #define DEFBOOL \
- .type = pvr2_ctl_bool
- #define DEFMASK(msk,tab) \
- .type = pvr2_ctl_bitmask, \
- .def.type_bitmask.valid_bits = msk, \
- .def.type_bitmask.bit_names = tab
- #define DEFREF(vname) \
- .set_value = ctrl_set_##vname, \
- .get_value = ctrl_get_##vname, \
- .is_dirty = ctrl_isdirty_##vname, \
- .clear_dirty = ctrl_cleardirty_##vname
- #define VCREATE_FUNCS(vname) \
- static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \
- {*vp = cptr->hdw->vname##_val; return 0;} \
- static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \
- {cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \
- static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \
- {return cptr->hdw->vname##_dirty != 0;} \
- static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \
- {cptr->hdw->vname##_dirty = 0;}
- VCREATE_FUNCS(brightness)
- VCREATE_FUNCS(contrast)
- VCREATE_FUNCS(saturation)
- VCREATE_FUNCS(hue)
- VCREATE_FUNCS(volume)
- VCREATE_FUNCS(balance)
- VCREATE_FUNCS(bass)
- VCREATE_FUNCS(treble)
- VCREATE_FUNCS(mute)
- VCREATE_FUNCS(input)
- VCREATE_FUNCS(audiomode)
- VCREATE_FUNCS(res_hor)
- VCREATE_FUNCS(res_ver)
- VCREATE_FUNCS(srate)
- #define MIN_FREQ 55250000L
- #define MAX_FREQ 850000000L
- /* Table definition of all controls which can be manipulated */
- static const struct pvr2_ctl_info control_defs[] = {
- {
- .v4l_id = V4L2_CID_BRIGHTNESS,
- .desc = "Brightness",
- .name = "brightness",
- .default_value = 128,
- DEFREF(brightness),
- DEFINT(0,255),
- },{
- .v4l_id = V4L2_CID_CONTRAST,
- .desc = "Contrast",
- .name = "contrast",
- .default_value = 68,
- DEFREF(contrast),
- DEFINT(0,127),
- },{
- .v4l_id = V4L2_CID_SATURATION,
- .desc = "Saturation",
- .name = "saturation",
- .default_value = 64,
- DEFREF(saturation),
- DEFINT(0,127),
- },{
- .v4l_id = V4L2_CID_HUE,
- .desc = "Hue",
- .name = "hue",
- .default_value = 0,
- DEFREF(hue),
- DEFINT(-128,127),
- },{
- .v4l_id = V4L2_CID_AUDIO_VOLUME,
- .desc = "Volume",
- .name = "volume",
- .default_value = 65535,
- DEFREF(volume),
- DEFINT(0,65535),
- },{
- .v4l_id = V4L2_CID_AUDIO_BALANCE,
- .desc = "Balance",
- .name = "balance",
- .default_value = 0,
- DEFREF(balance),
- DEFINT(-32768,32767),
- },{
- .v4l_id = V4L2_CID_AUDIO_BASS,
- .desc = "Bass",
- .name = "bass",
- .default_value = 0,
- DEFREF(bass),
- DEFINT(-32768,32767),
- },{
- .v4l_id = V4L2_CID_AUDIO_TREBLE,
- .desc = "Treble",
- .name = "treble",
- .default_value = 0,
- DEFREF(treble),
- DEFINT(-32768,32767),
- },{
- .v4l_id = V4L2_CID_AUDIO_MUTE,
- .desc = "Mute",
- .name = "mute",
- .default_value = 0,
- DEFREF(mute),
- DEFBOOL,
- },{
- .desc = "Video Source",
- .name = "input",
- .internal_id = PVR2_CID_INPUT,
- .default_value = PVR2_CVAL_INPUT_TV,
- DEFREF(input),
- DEFENUM(control_values_input),
- },{
- .desc = "Audio Mode",
- .name = "audio_mode",
- .internal_id = PVR2_CID_AUDIOMODE,
- .default_value = V4L2_TUNER_MODE_STEREO,
- DEFREF(audiomode),
- DEFENUM(control_values_audiomode),
- },{
- .desc = "Horizontal capture resolution",
- .name = "resolution_hor",
- .internal_id = PVR2_CID_HRES,
- .default_value = 720,
- DEFREF(res_hor),
- DEFINT(19,720),
- /* Hook in check for clamp on horizontal resolution in
- order to avoid unsolved problem involving cx25840. */
- .get_max_value = ctrl_hres_max_get,
- .get_min_value = ctrl_hres_min_get,
- },{
- .desc = "Vertical capture resolution",
- .name = "resolution_ver",
- .internal_id = PVR2_CID_VRES,
- .default_value = 480,
- DEFREF(res_ver),
- DEFINT(17,576),
- /* Hook in check for video standard and adjust maximum
- depending on the standard. */
- .get_max_value = ctrl_vres_max_get,
- .get_min_value = ctrl_vres_min_get,
- },{
- .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
- .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
- .desc = "Audio Sampling Frequency",
- .name = "srate",
- DEFREF(srate),
- DEFENUM(control_values_srate),
- },{
- .desc = "Tuner Frequency (Hz)",
- .name = "frequency",
- .internal_id = PVR2_CID_FREQUENCY,
- .default_value = 175250000L,
- .set_value = ctrl_freq_set,
- .get_value = ctrl_freq_get,
- .is_dirty = ctrl_freq_is_dirty,
- .clear_dirty = ctrl_freq_clear_dirty,
- DEFINT(MIN_FREQ,MAX_FREQ),
- },{
- .desc = "Channel",
- .name = "channel",
- .set_value = ctrl_channel_set,
- .get_value = ctrl_channel_get,
- DEFINT(0,FREQTABLE_SIZE),
- },{
- .desc = "Channel Program Frequency",
- .name = "freq_table_value",
- .set_value = ctrl_channelfreq_set,
- .get_value = ctrl_channelfreq_get,
- DEFINT(MIN_FREQ,MAX_FREQ),
- },{
- .desc = "Channel Program ID",
- .name = "freq_table_channel",
- .set_value = ctrl_channelprog_set,
- .get_value = ctrl_channelprog_get,
- DEFINT(0,FREQTABLE_SIZE),
- },{
- .desc = "Streaming Enabled",
- .name = "streaming_enabled",
- .get_value = ctrl_streamingenabled_get,
- DEFBOOL,
- },{
- .desc = "USB Speed",
- .name = "usb_speed",
- .get_value = ctrl_hsm_get,
- DEFENUM(control_values_hsm),
- },{
- .desc = "Signal Present",
- .name = "signal_present",
- .get_value = ctrl_signal_get,
- DEFBOOL,
- },{
- .desc = "Video Standards Available Mask",
- .name = "video_standard_mask_available",
- .internal_id = PVR2_CID_STDAVAIL,
- .skip_init = !0,
- .get_value = ctrl_stdavail_get,
- .set_value = ctrl_stdavail_set,
- .val_to_sym = ctrl_std_val_to_sym,
- .sym_to_val = ctrl_std_sym_to_val,
- .type = pvr2_ctl_bitmask,
- },{
- .desc = "Video Standards In Use Mask",
- .name = "video_standard_mask_active",
- .internal_id = PVR2_CID_STDCUR,
- .skip_init = !0,
- .get_value = ctrl_stdcur_get,
- .set_value = ctrl_stdcur_set,
- .is_dirty = ctrl_stdcur_is_dirty,
- .clear_dirty = ctrl_stdcur_clear_dirty,
- .val_to_sym = ctrl_std_val_to_sym,
- .sym_to_val = ctrl_std_sym_to_val,
- .type = pvr2_ctl_bitmask,
- },{
- .desc = "Subsystem enabled mask",
- .name = "debug_subsys_mask",
- .skip_init = !0,
- .get_value = ctrl_subsys_get,
- .set_value = ctrl_subsys_set,
- DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
- },{
- .desc = "Subsystem stream mask",
- .name = "debug_subsys_stream_mask",
- .skip_init = !0,
- .get_value = ctrl_subsys_stream_get,
- .set_value = ctrl_subsys_stream_set,
- DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
- },{
- .desc = "Video Standard Name",
- .name = "video_standard",
- .internal_id = PVR2_CID_STDENUM,
- .skip_init = !0,
- .get_value = ctrl_stdenumcur_get,
- .set_value = ctrl_stdenumcur_set,
- .is_dirty = ctrl_stdenumcur_is_dirty,
- .clear_dirty = ctrl_stdenumcur_clear_dirty,
- .type = pvr2_ctl_enum,
- }
- };
- #define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
- const char *pvr2_config_get_name(enum pvr2_config cfg)
- {
- switch (cfg) {
- case pvr2_config_empty: return "empty";
- case pvr2_config_mpeg: return "mpeg";
- case pvr2_config_vbi: return "vbi";
- case pvr2_config_radio: return "radio";
- }
- return "<unknown>";
- }
- struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw)
- {
- return hdw->usb_dev;
- }
- unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
- {
- return hdw->serial_number;
- }
- int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
- {
- return hdw->unit_number;
- }
- /* Attempt to locate one of the given set of files. Messages are logged
- appropriate to what has been found. The return value will be 0 or
- greater on success (it will be the index of the file name found) and
- fw_entry will be filled in. Otherwise a negative error is returned on
- failure. If the return value is -ENOENT then no viable firmware file
- could be located. */
- static int pvr2_locate_firmware(struct pvr2_hdw *hdw,
- const struct firmware **fw_entry,
- const char *fwtypename,
- unsigned int fwcount,
- const char *fwnames[])
- {
- unsigned int idx;
- int ret = -EINVAL;
- for (idx = 0; idx < fwcount; idx++) {
- ret = request_firmware(fw_entry,
- fwnames[idx],
- &hdw->usb_dev->dev);
- if (!ret) {
- trace_firmware("Located %s firmware: %s;"
- " uploading...",
- fwtypename,
- fwnames[idx]);
- return idx;
- }
- if (ret == -ENOENT) continue;
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "request_firmware fatal error with code=%d",ret);
- return ret;
- }
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "***WARNING***"
- " Device %s firmware"
- " seems to be missing.",
- fwtypename);
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Did you install the pvrusb2 firmware files"
- " in their proper location?");
- if (fwcount == 1) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "request_firmware unable to locate %s file %s",
- fwtypename,fwnames[0]);
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "request_firmware unable to locate"
- " one of the following %s files:",
- fwtypename);
- for (idx = 0; idx < fwcount; idx++) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "request_firmware: Failed to find %s",
- fwnames[idx]);
- }
- }
- return ret;
- }
- /*
- * pvr2_upload_firmware1().
- *
- * Send the 8051 firmware to the device. After the upload, arrange for
- * device to re-enumerate.
- *
- * NOTE : the pointer to the firmware data given by request_firmware()
- * is not suitable for an usb transaction.
- *
- */
- static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
- {
- const struct firmware *fw_entry = NULL;
- void *fw_ptr;
- unsigned int pipe;
- int ret;
- u16 address;
- static const char *fw_files_29xxx[] = {
- "v4l-pvrusb2-29xxx-01.fw",
- };
- static const char *fw_files_24xxx[] = {
- "v4l-pvrusb2-24xxx-01.fw",
- };
- static const struct pvr2_string_table fw_file_defs[] = {
- [PVR2_HDW_TYPE_29XXX] = {
- fw_files_29xxx,
- sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
- },
- [PVR2_HDW_TYPE_24XXX] = {
- fw_files_24xxx,
- sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
- },
- };
- hdw->fw1_state = FW1_STATE_FAILED; // default result
- trace_firmware("pvr2_upload_firmware1");
- ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
- fw_file_defs[hdw->hdw_type].cnt,
- fw_file_defs[hdw->hdw_type].lst);
- if (ret < 0) {
- if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
- return ret;
- }
- usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0);
- usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
- pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
- if (fw_entry->size != 0x2000){
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,"wrong fx2 firmware size");
- release_firmware(fw_entry);
- return -ENOMEM;
- }
- fw_ptr = kmalloc(0x800, GFP_KERNEL);
- if (fw_ptr == NULL){
- release_firmware(fw_entry);
- return -ENOMEM;
- }
- /* We have to hold the CPU during firmware upload. */
- pvr2_hdw_cpureset_assert(hdw,1);
- /* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes
- chunk. */
- ret = 0;
- for(address = 0; address < fw_entry->size; address += 0x800) {
- memcpy(fw_ptr, fw_entry->data + address, 0x800);
- ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address,
- 0, fw_ptr, 0x800, HZ);
- }
- trace_firmware("Upload done, releasing device's CPU");
- /* Now release the CPU. It will disconnect and reconnect later. */
- pvr2_hdw_cpureset_assert(hdw,0);
- kfree(fw_ptr);
- release_firmware(fw_entry);
- trace_firmware("Upload done (%d bytes sent)",ret);
- /* We should have written 8192 bytes */
- if (ret == 8192) {
- hdw->fw1_state = FW1_STATE_RELOAD;
- return 0;
- }
- return -EIO;
- }
- /*
- * pvr2_upload_firmware2()
- *
- * This uploads encoder firmware on endpoint 2.
- *
- */
- int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
- {
- const struct firmware *fw_entry = NULL;
- void *fw_ptr;
- unsigned int pipe, fw_len, fw_done;
- int actual_length;
- int ret = 0;
- int fwidx;
- static const char *fw_files[] = {
- CX2341X_FIRM_ENC_FILENAME,
- };
- trace_firmware("pvr2_upload_firmware2");
- ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
- sizeof(fw_files)/sizeof(fw_files[0]),
- fw_files);
- if (ret < 0) return ret;
- fwidx = ret;
- ret = 0;
- /* Since we're about to completely reinitialize the encoder,
- invalidate our cached copy of its configuration state. Next
- time we configure the encoder, then we'll fully configure it. */
- hdw->enc_cur_valid = 0;
- /* First prepare firmware loading */
- ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
- ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
- ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
- ret |= pvr2_hdw_cmd_deep_reset(hdw);
- ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/
- ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/
- ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
- ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/
- ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/
- ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/
- ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/
- ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/
- ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/
- ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
- ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
- ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
- ret |= pvr2_write_u8(hdw, 0x52, 0);
- ret |= pvr2_write_u16(hdw, 0x0600, 0);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "firmware2 upload prep failed, ret=%d",ret);
- release_firmware(fw_entry);
- return ret;
- }
- /* Now send firmware */
- fw_len = fw_entry->size;
- if (fw_len % FIRMWARE_CHUNK_SIZE) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "size of %s firmware"
- " must be a multiple of 8192B",
- fw_files[fwidx]);
- release_firmware(fw_entry);
- return -1;
- }
- fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
- if (fw_ptr == NULL){
- release_firmware(fw_entry);
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "failed to allocate memory for firmware2 upload");
- return -ENOMEM;
- }
- pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
- for (fw_done = 0 ; (fw_done < fw_len) && !ret ;
- fw_done += FIRMWARE_CHUNK_SIZE ) {
- int i;
- memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE);
- /* Usbsnoop log shows that we must swap bytes... */
- for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++)
- ((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]);
- ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,
- FIRMWARE_CHUNK_SIZE,
- &actual_length, HZ);
- ret |= (actual_length != FIRMWARE_CHUNK_SIZE);
- }
- trace_firmware("upload of %s : %i / %i ",
- fw_files[fwidx],fw_done,fw_len);
- kfree(fw_ptr);
- release_firmware(fw_entry);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "firmware2 upload transfer failure");
- return ret;
- }
- /* Finish upload */
- ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
- ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
- ret |= pvr2_write_u16(hdw, 0x0600, 0);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "firmware2 upload post-proc failure");
- } else {
- hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_FIRMWARE);
- }
- return ret;
- }
- #define FIRMWARE_RECOVERY_BITS \
- ((1<<PVR2_SUBSYS_B_ENC_CFG) | \
- (1<<PVR2_SUBSYS_B_ENC_RUN) | \
- (1<<PVR2_SUBSYS_B_ENC_FIRMWARE) | \
- (1<<PVR2_SUBSYS_B_USBSTREAM_RUN))
- /*
- This single function is key to pretty much everything. The pvrusb2
- device can logically be viewed as a series of subsystems which can be
- stopped / started or unconfigured / configured. To get things streaming,
- one must configure everything and start everything, but there may be
- various reasons over time to deconfigure something or stop something.
- This function handles all of this activity. Everything EVERYWHERE that
- must affect a subsystem eventually comes here to do the work.
- The current state of all subsystems is represented by a single bit mask,
- known as subsys_enabled_mask. The bit positions are defined by the
- PVR2_SUBSYS_xxxx macros, with one subsystem per bit position. At any
- time the set of configured or active subsystems can be queried just by
- looking at that mask. To change bits in that mask, this function here
- must be called. The "msk" argument indicates which bit positions to
- change, and the "val" argument defines the new values for the positions
- defined by "msk".
- There is a priority ordering of starting / stopping things, and for
- multiple requested changes, this function implements that ordering.
- (Thus we will act on a request to load encoder firmware before we
- configure the encoder.) In addition to priority ordering, there is a
- recovery strategy implemented here. If a particular step fails and we
- detect that failure, this function will clear the affected subsystem bits
- and restart. Thus we have a means for recovering from a dead encoder:
- Clear all bits that correspond to subsystems that we need to restart /
- reconfigure and start over.
- */
- static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
- unsigned long msk,
- unsigned long val)
- {
- unsigned long nmsk;
- unsigned long vmsk;
- int ret;
- unsigned int tryCount = 0;
- if (!hdw->flag_ok) return;
- msk &= PVR2_SUBSYS_ALL;
- nmsk = (hdw->subsys_enabled_mask & ~msk) | (val & msk);
- nmsk &= PVR2_SUBSYS_ALL;
- for (;;) {
- tryCount++;
- if (!((nmsk ^ hdw->subsys_enabled_mask) &
- PVR2_SUBSYS_ALL)) break;
- if (tryCount > 4) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Too many retries when configuring device;"
- " giving up");
- pvr2_hdw_render_useless(hdw);
- break;
- }
- if (tryCount > 1) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Retrying device reconfiguration");
- }
- pvr2_trace(PVR2_TRACE_INIT,
- "subsys mask changing 0x%lx:0x%lx"
- " from 0x%lx to 0x%lx",
- msk,val,hdw->subsys_enabled_mask,nmsk);
- vmsk = (nmsk ^ hdw->subsys_enabled_mask) &
- hdw->subsys_enabled_mask;
- if (vmsk) {
- if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " pvr2_encoder_stop");
- ret = pvr2_encoder_stop(hdw);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Error recovery initiated");
- hdw->subsys_enabled_mask &=
- ~FIRMWARE_RECOVERY_BITS;
- continue;
- }
- }
- if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " pvr2_hdw_cmd_usbstream(0)");
- pvr2_hdw_cmd_usbstream(hdw,0);
- }
- if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " decoder disable");
- if (hdw->decoder_ctrl) {
- hdw->decoder_ctrl->enable(
- hdw->decoder_ctrl->ctxt,0);
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "WARNING:"
- " No decoder present");
- }
- hdw->subsys_enabled_mask &=
- ~(1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
- }
- if (vmsk & PVR2_SUBSYS_CFG_ALL) {
- hdw->subsys_enabled_mask &=
- ~(vmsk & PVR2_SUBSYS_CFG_ALL);
- }
- }
- vmsk = (nmsk ^ hdw->subsys_enabled_mask) & nmsk;
- if (vmsk) {
- if (vmsk & (1<<PVR2_SUBSYS_B_ENC_FIRMWARE)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " pvr2_upload_firmware2");
- ret = pvr2_upload_firmware2(hdw);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failure uploading encoder"
- " firmware");
- pvr2_hdw_render_useless(hdw);
- break;
- }
- }
- if (vmsk & (1<<PVR2_SUBSYS_B_ENC_CFG)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " pvr2_encoder_configure");
- ret = pvr2_encoder_configure(hdw);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Error recovery initiated");
- hdw->subsys_enabled_mask &=
- ~FIRMWARE_RECOVERY_BITS;
- continue;
- }
- }
- if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " decoder enable");
- if (hdw->decoder_ctrl) {
- hdw->decoder_ctrl->enable(
- hdw->decoder_ctrl->ctxt,!0);
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "WARNING:"
- " No decoder present");
- }
- hdw->subsys_enabled_mask |=
- (1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
- }
- if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " pvr2_hdw_cmd_usbstream(1)");
- pvr2_hdw_cmd_usbstream(hdw,!0);
- }
- if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
- pvr2_trace(PVR2_TRACE_CTL,
- "/*---TRACE_CTL----*/"
- " pvr2_encoder_start");
- ret = pvr2_encoder_start(hdw);
- if (ret) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Error recovery initiated");
- hdw->subsys_enabled_mask &=
- ~FIRMWARE_RECOVERY_BITS;
- continue;
- }
- }
- }
- }
- }
- void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
- unsigned long msk,unsigned long val)
- {
- LOCK_TAKE(hdw->big_lock); do {
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,msk,val);
- } while (0); LOCK_GIVE(hdw->big_lock);
- }
- unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw)
- {
- return hdw->subsys_enabled_mask;
- }
- unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw)
- {
- return hdw->subsys_stream_mask;
- }
- static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
- unsigned long msk,
- unsigned long val)
- {
- unsigned long val2;
- msk &= PVR2_SUBSYS_ALL;
- val2 = ((hdw->subsys_stream_mask & ~msk) | (val & msk));
- pvr2_trace(PVR2_TRACE_INIT,
- "stream mask changing 0x%lx:0x%lx from 0x%lx to 0x%lx",
- msk,val,hdw->subsys_stream_mask,val2);
- hdw->subsys_stream_mask = val2;
- }
- void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
- unsigned long msk,
- unsigned long val)
- {
- LOCK_TAKE(hdw->big_lock); do {
- pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,msk,val);
- } while (0); LOCK_GIVE(hdw->big_lock);
- }
- static int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl)
- {
- if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0;
- if (enableFl) {
- pvr2_trace(PVR2_TRACE_START_STOP,
- "/*--TRACE_STREAM--*/ enable");
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,~0);
- } else {
- pvr2_trace(PVR2_TRACE_START_STOP,
- "/*--TRACE_STREAM--*/ disable");
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0);
- }
- if (!hdw->flag_ok) return -EIO;
- hdw->flag_streaming_enabled = enableFl != 0;
- return 0;
- }
- int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
- {
- return hdw->flag_streaming_enabled != 0;
- }
- int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
- {
- int ret;
- LOCK_TAKE(hdw->big_lock); do {
- ret = pvr2_hdw_set_streaming_no_lock(hdw,enable_flag);
- } while (0); LOCK_GIVE(hdw->big_lock);
- return ret;
- }
- static int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw,
- enum pvr2_config config)
- {
- unsigned long sm = hdw->subsys_enabled_mask;
- if (!hdw->flag_ok) return -EIO;
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0);
- hdw->config = config;
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,sm);
- return 0;
- }
- int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config)
- {
- int ret;
- if (!hdw->flag_ok) return -EIO;
- LOCK_TAKE(hdw->big_lock);
- ret = pvr2_hdw_set_stream_type_no_lock(hdw,config);
- LOCK_GIVE(hdw->big_lock);
- return ret;
- }
- static int get_default_tuner_type(struct pvr2_hdw *hdw)
- {
- int unit_number = hdw->unit_number;
- int tp = -1;
- if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
- tp = tuner[unit_number];
- }
- if (tp < 0) return -EINVAL;
- hdw->tuner_type = tp;
- return 0;
- }
- static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw)
- {
- int unit_number = hdw->unit_number;
- int tp = 0;
- if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
- tp = video_std[unit_number];
- }
- return tp;
- }
- static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
- {
- int unit_number = hdw->unit_number;
- int tp = 0;
- if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
- tp = tolerance[unit_number];
- }
- return tp;
- }
- static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
- {
- /* Try a harmless request to fetch the eeprom's address over
- endpoint 1. See what happens. Only the full FX2 image can
- respond to this. If this probe fails then likely the FX2
- firmware needs be loaded. */
- int result;
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = 0xeb;
- result = pvr2_send_request_ex(hdw,HZ*1,!0,
- hdw->cmd_buffer,1,
- hdw->cmd_buffer,1);
- if (result < 0) break;
- } while(0); LOCK_GIVE(hdw->ctl_lock);
- if (result) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Probe of device endpoint 1 result status %d",
- result);
- } else {
- pvr2_trace(PVR2_TRACE_INIT,
- "Probe of device endpoint 1 succeeded");
- }
- return result == 0;
- }
- static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
- {
- char buf[40];
- unsigned int bcnt;
- v4l2_std_id std1,std2;
- std1 = get_default_standard(hdw);
- bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
- pvr2_trace(PVR2_TRACE_INIT,
- "Supported video standard(s) reported by eeprom: %.*s",
- bcnt,buf);
- hdw->std_mask_avail = hdw->std_mask_eeprom;
- std2 = std1 & ~hdw->std_mask_avail;
- if (std2) {
- bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
- pvr2_trace(PVR2_TRACE_INIT,
- "Expanding supported video standards"
- " to include: %.*s",
- bcnt,buf);
- hdw->std_mask_avail |= std2;
- }
- pvr2_hdw_internal_set_std_avail(hdw);
- if (std1) {
- bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
- pvr2_trace(PVR2_TRACE_INIT,
- "Initial video standard forced to %.*s",
- bcnt,buf);
- hdw->std_mask_cur = std1;
- hdw->std_dirty = !0;
- pvr2_hdw_internal_find_stdenum(hdw);
- return;
- }
- if (hdw->std_enum_cnt > 1) {
- // Autoselect the first listed standard
- hdw->std_enum_cur = 1;
- hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id;
- hdw->std_dirty = !0;
- pvr2_trace(PVR2_TRACE_INIT,
- "Initial video standard auto-selected to %s",
- hdw->std_defs[hdw->std_enum_cur-1].name);
- return;
- }
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Unable to select a viable initial video standard");
- }
- static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
- {
- int ret;
- unsigned int idx;
- struct pvr2_ctrl *cptr;
- int reloadFl = 0;
- if (!reloadFl) {
- reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
- == 0);
- if (reloadFl) {
- pvr2_trace(PVR2_TRACE_INIT,
- "USB endpoint config looks strange"
- "; possibly firmware needs to be loaded");
- }
- }
- if (!reloadFl) {
- reloadFl = !pvr2_hdw_check_firmware(hdw);
- if (reloadFl) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Check for FX2 firmware failed"
- "; possibly firmware needs to be loaded");
- }
- }
- if (reloadFl) {
- if (pvr2_upload_firmware1(hdw) != 0) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failure uploading firmware1");
- }
- return;
- }
- hdw->fw1_state = FW1_STATE_OK;
- if (initusbreset) {
- pvr2_hdw_device_reset(hdw);
- }
- if (!pvr2_hdw_dev_ok(hdw)) return;
- for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) {
- request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]);
- }
- pvr2_hdw_cmd_powerup(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
- if (pvr2_upload_firmware2(hdw)){
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!");
- pvr2_hdw_render_useless(hdw);
- return;
- }
- // This step MUST happen after the earlier powerup step.
- pvr2_i2c_core_init(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
- for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
- cptr = hdw->controls + idx;
- if (cptr->info->skip_init) continue;
- if (!cptr->info->set_value) continue;
- cptr->info->set_value(cptr,~0,cptr->info->default_value);
- }
- // Do not use pvr2_reset_ctl_endpoints() here. It is not
- // thread-safe against the normal pvr2_send_request() mechanism.
- // (We should make it thread safe).
- ret = pvr2_hdw_get_eeprom_addr(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
- if (ret < 0) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Unable to determine location of eeprom, skipping");
- } else {
- hdw->eeprom_addr = ret;
- pvr2_eeprom_analyze(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
- }
- pvr2_hdw_setup_std(hdw);
- if (!get_default_tuner_type(hdw)) {
- pvr2_trace(PVR2_TRACE_INIT,
- "pvr2_hdw_setup: Tuner type overridden to %d",
- hdw->tuner_type);
- }
- hdw->tuner_updated = !0;
- pvr2_i2c_core_check_stale(hdw);
- hdw->tuner_updated = 0;
- if (!pvr2_hdw_dev_ok(hdw)) return;
- pvr2_hdw_commit_ctl_internal(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
- hdw->vid_stream = pvr2_stream_create();
- if (!pvr2_hdw_dev_ok(hdw)) return;
- pvr2_trace(PVR2_TRACE_INIT,
- "pvr2_hdw_setup: video stream is %p",hdw->vid_stream);
- if (hdw->vid_stream) {
- idx = get_default_error_tolerance(hdw);
- if (idx) {
- pvr2_trace(PVR2_TRACE_INIT,
- "pvr2_hdw_setup: video stream %p"
- " setting tolerance %u",
- hdw->vid_stream,idx);
- }
- pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
- PVR2_VID_ENDPOINT,idx);
- }
- if (!pvr2_hdw_dev_ok(hdw)) return;
- /* Make sure everything is up to date */
- pvr2_i2c_core_sync(hdw);
- if (!pvr2_hdw_dev_ok(hdw)) return;
- hdw->flag_init_ok = !0;
- }
- int pvr2_hdw_setup(struct pvr2_hdw *hdw)
- {
- pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw);
- LOCK_TAKE(hdw->big_lock); do {
- pvr2_hdw_setup_low(hdw);
- pvr2_trace(PVR2_TRACE_INIT,
- "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",
- hdw,hdw->flag_ok,hdw->flag_init_ok);
- if (pvr2_hdw_dev_ok(hdw)) {
- if (pvr2_hdw_init_ok(hdw)) {
- pvr2_trace(
- PVR2_TRACE_INFO,
- "Device initialization"
- " completed successfully.");
- break;
- }
- if (hdw->fw1_state == FW1_STATE_RELOAD) {
- pvr2_trace(
- PVR2_TRACE_INFO,
- "Device microcontroller firmware"
- " (re)loaded; it should now reset"
- " and reconnect.");
- break;
- }
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Device initialization was not successful.");
- if (hdw->fw1_state == FW1_STATE_MISSING) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Giving up since device"
- " microcontroller firmware"
- " appears to be missing.");
- break;
- }
- }
- if (procreload) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Attempting pvrusb2 recovery by reloading"
- " primary firmware.");
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "If this works, device should disconnect"
- " and reconnect in a sane state.");
- hdw->fw1_state = FW1_STATE_UNKNOWN;
- pvr2_upload_firmware1(hdw);
- } else {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "***WARNING*** pvrusb2 device hardware"
- " appears to be jammed"
- " and I can't clear it.");
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "You might need to power cycle"
- " the pvrusb2 device"
- " in order to recover.");
- }
- } while (0); LOCK_GIVE(hdw->big_lock);
- pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
- return hdw->flag_init_ok;
- }
- /* Create and return a structure for interacting with the underlying
- hardware */
- struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
- const struct usb_device_id *devid)
- {
- unsigned int idx,cnt1,cnt2;
- struct pvr2_hdw *hdw;
- unsigned int hdw_type;
- int valid_std_mask;
- struct pvr2_ctrl *cptr;
- __u8 ifnum;
- struct v4l2_queryctrl qctrl;
- struct pvr2_ctl_info *ciptr;
- hdw_type = devid - pvr2_device_table;
- if (hdw_type >=
- sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Bogus device type of %u reported",hdw_type);
- return NULL;
- }
- hdw = kmalloc(sizeof(*hdw),GFP_KERNEL);
- pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
- hdw,pvr2_device_names[hdw_type]);
- if (!hdw) goto fail;
- memset(hdw,0,sizeof(*hdw));
- cx2341x_fill_defaults(&hdw->enc_ctl_state);
- hdw->control_cnt = CTRLDEF_COUNT;
- hdw->control_cnt += MPEGDEF_COUNT;
- hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
- GFP_KERNEL);
- if (!hdw->controls) goto fail;
- memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt);
- hdw->hdw_type = hdw_type;
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- cptr->hdw = hdw;
- }
- for (idx = 0; idx < 32; idx++) {
- hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
- }
- for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
- cptr = hdw->controls + idx;
- cptr->info = control_defs+idx;
- }
- /* Define and configure additional controls from cx2341x module. */
- hdw->mpeg_ctrl_info = kmalloc(
- sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
- if (!hdw->mpeg_ctrl_info) goto fail;
- memset(hdw->mpeg_ctrl_info,0,
- sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT);
- for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
- cptr = hdw->controls + idx + CTRLDEF_COUNT;
- ciptr = &(hdw->mpeg_ctrl_info[idx].info);
- ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
- ciptr->name = mpeg_ids[idx].strid;
- ciptr->v4l_id = mpeg_ids[idx].id;
- ciptr->skip_init = !0;
- ciptr->get_value = ctrl_cx2341x_get;
- ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
- ciptr->is_dirty = ctrl_cx2341x_is_dirty;
- if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
- qctrl.id = ciptr->v4l_id;
- cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
- if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
- ciptr->set_value = ctrl_cx2341x_set;
- }
- strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,
- PVR2_CTLD_INFO_DESC_SIZE);
- hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;
- ciptr->default_value = qctrl.default_value;
- switch (qctrl.type) {
- default:
- case V4L2_CTRL_TYPE_INTEGER:
- ciptr->type = pvr2_ctl_int;
- ciptr->def.type_int.min_value = qctrl.minimum;
- ciptr->def.type_int.max_value = qctrl.maximum;
- break;
- case V4L2_CTRL_TYPE_BOOLEAN:
- ciptr->type = pvr2_ctl_bool;
- break;
- case V4L2_CTRL_TYPE_MENU:
- ciptr->type = pvr2_ctl_enum;
- ciptr->def.type_enum.value_names =
- cx2341x_ctrl_get_menu(ciptr->v4l_id);
- for (cnt1 = 0;
- ciptr->def.type_enum.value_names[cnt1] != NULL;
- cnt1++) { }
- ciptr->def.type_enum.count = cnt1;
- break;
- }
- cptr->info = ciptr;
- }
- // Initialize video standard enum dynamic control
- cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM);
- if (cptr) {
- memcpy(&hdw->std_info_enum,cptr->info,
- sizeof(hdw->std_info_enum));
- cptr->info = &hdw->std_info_enum;
- }
- // Initialize control data regarding video standard masks
- valid_std_mask = pvr2_std_get_usable();
- for (idx = 0; idx < 32; idx++) {
- if (!(valid_std_mask & (1 << idx))) continue;
- cnt1 = pvr2_std_id_to_str(
- hdw->std_mask_names[idx],
- sizeof(hdw->std_mask_names[idx])-1,
- 1 << idx);
- hdw->std_mask_names[idx][cnt1] = 0;
- }
- cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
- if (cptr) {
- memcpy(&hdw->std_info_avail,cptr->info,
- sizeof(hdw->std_info_avail));
- cptr->info = &hdw->std_info_avail;
- hdw->std_info_avail.def.type_bitmask.bit_names =
- hdw->std_mask_ptrs;
- hdw->std_info_avail.def.type_bitmask.valid_bits =
- valid_std_mask;
- }
- cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
- if (cptr) {
- memcpy(&hdw->std_info_cur,cptr->info,
- sizeof(hdw->std_info_cur));
- cptr->info = &hdw->std_info_cur;
- hdw->std_info_cur.def.type_bitmask.bit_names =
- hdw->std_mask_ptrs;
- hdw->std_info_avail.def.type_bitmask.valid_bits =
- valid_std_mask;
- }
- hdw->eeprom_addr = -1;
- hdw->unit_number = -1;
- hdw->v4l_minor_number = -1;
- hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
- if (!hdw->ctl_write_buffer) goto fail;
- hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
- if (!hdw->ctl_read_buffer) goto fail;
- hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);
- if (!hdw->ctl_write_urb) goto fail;
- hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
- if (!hdw->ctl_read_urb) goto fail;
- down(&pvr2_unit_sem); do {
- for (idx = 0; idx < PVR_NUM; idx++) {
- if (unit_pointers[idx]) continue;
- hdw->unit_number = idx;
- unit_pointers[idx] = hdw;
- break;
- }
- } while (0); up(&pvr2_unit_sem);
- cnt1 = 0;
- cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
- cnt1 += cnt2;
- if (hdw->unit_number >= 0) {
- cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",
- ('a' + hdw->unit_number));
- cnt1 += cnt2;
- }
- if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
- hdw->name[cnt1] = 0;
- pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
- hdw->unit_number,hdw->name);
- hdw->tuner_type = -1;
- hdw->flag_ok = !0;
- /* Initialize the mask of subsystems that we will shut down when we
- stop streaming. */
- hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL;
- hdw->subsys_stream_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
- pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx",
- hdw->subsys_stream_mask);
- hdw->usb_intf = intf;
- hdw->usb_dev = interface_to_usbdev(intf);
- ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
- usb_set_interface(hdw->usb_dev,ifnum,0);
- mutex_init(&hdw->ctl_lock_mutex);
- mutex_init(&hdw->big_lock_mutex);
- return hdw;
- fail:
- if (hdw) {
- if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb);
- if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb);
- if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
- if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
- if (hdw->controls) kfree(hdw->controls);
- if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
- kfree(hdw);
- }
- return NULL;
- }
- /* Remove _all_ associations between this driver and the underlying USB
- layer. */
- static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
- {
- if (hdw->flag_disconnected) return;
- pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);
- if (hdw->ctl_read_urb) {
- usb_kill_urb(hdw->ctl_read_urb);
- usb_free_urb(hdw->ctl_read_urb);
- hdw->ctl_read_urb = NULL;
- }
- if (hdw->ctl_write_urb) {
- usb_kill_urb(hdw->ctl_write_urb);
- usb_free_urb(hdw->ctl_write_urb);
- hdw->ctl_write_urb = NULL;
- }
- if (hdw->ctl_read_buffer) {
- kfree(hdw->ctl_read_buffer);
- hdw->ctl_read_buffer = NULL;
- }
- if (hdw->ctl_write_buffer) {
- kfree(hdw->ctl_write_buffer);
- hdw->ctl_write_buffer = NULL;
- }
- pvr2_hdw_render_useless_unlocked(hdw);
- hdw->flag_disconnected = !0;
- hdw->usb_dev = NULL;
- hdw->usb_intf = NULL;
- }
- /* Destroy hardware interaction structure */
- void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
- {
- pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
- if (hdw->fw_buffer) {
- kfree(hdw->fw_buffer);
- hdw->fw_buffer = NULL;
- }
- if (hdw->vid_stream) {
- pvr2_stream_destroy(hdw->vid_stream);
- hdw->vid_stream = NULL;
- }
- if (hdw->audio_stat) {
- hdw->audio_stat->detach(hdw->audio_stat->ctxt);
- }
- if (hdw->decoder_ctrl) {
- hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
- }
- pvr2_i2c_core_done(hdw);
- pvr2_hdw_remove_usb_stuff(hdw);
- down(&pvr2_unit_sem); do {
- if ((hdw->unit_number >= 0) &&
- (hdw->unit_number < PVR_NUM) &&
- (unit_pointers[hdw->unit_number] == hdw)) {
- unit_pointers[hdw->unit_number] = NULL;
- }
- } while (0); up(&pvr2_unit_sem);
- if (hdw->controls) kfree(hdw->controls);
- if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
- if (hdw->std_defs) kfree(hdw->std_defs);
- if (hdw->std_enum_names) kfree(hdw->std_enum_names);
- kfree(hdw);
- }
- int pvr2_hdw_init_ok(struct pvr2_hdw *hdw)
- {
- return hdw->flag_init_ok;
- }
- int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw)
- {
- return (hdw && hdw->flag_ok);
- }
- /* Called when hardware has been unplugged */
- void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
- {
- pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
- LOCK_TAKE(hdw->big_lock);
- LOCK_TAKE(hdw->ctl_lock);
- pvr2_hdw_remove_usb_stuff(hdw);
- LOCK_GIVE(hdw->ctl_lock);
- LOCK_GIVE(hdw->big_lock);
- }
- // Attempt to autoselect an appropriate value for std_enum_cur given
- // whatever is currently in std_mask_cur
- static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw)
- {
- unsigned int idx;
- for (idx = 1; idx < hdw->std_enum_cnt; idx++) {
- if (hdw->std_defs[idx-1].id == hdw->std_mask_cur) {
- hdw->std_enum_cur = idx;
- return;
- }
- }
- hdw->std_enum_cur = 0;
- }
- // Calculate correct set of enumerated standards based on currently known
- // set of available standards bits.
- static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw)
- {
- struct v4l2_standard *newstd;
- unsigned int std_cnt;
- unsigned int idx;
- newstd = pvr2_std_create_enum(&std_cnt,hdw->std_mask_avail);
- if (hdw->std_defs) {
- kfree(hdw->std_defs);
- hdw->std_defs = NULL;
- }
- hdw->std_enum_cnt = 0;
- if (hdw->std_enum_names) {
- kfree(hdw->std_enum_names);
- hdw->std_enum_names = NULL;
- }
- if (!std_cnt) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "WARNING: Failed to identify any viable standards");
- }
- hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL);
- hdw->std_enum_names[0] = "none";
- for (idx = 0; idx < std_cnt; idx++) {
- hdw->std_enum_names[idx+1] =
- newstd[idx].name;
- }
- // Set up the dynamic control for this standard
- hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names;
- hdw->std_info_enum.def.type_enum.count = std_cnt+1;
- hdw->std_defs = newstd;
- hdw->std_enum_cnt = std_cnt+1;
- hdw->std_enum_cur = 0;
- hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
- }
- int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,
- struct v4l2_standard *std,
- unsigned int idx)
- {
- int ret = -EINVAL;
- if (!idx) return ret;
- LOCK_TAKE(hdw->big_lock); do {
- if (idx >= hdw->std_enum_cnt) break;
- idx--;
- memcpy(std,hdw->std_defs+idx,sizeof(*std));
- ret = 0;
- } while (0); LOCK_GIVE(hdw->big_lock);
- return ret;
- }
- /* Get the number of defined controls */
- unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
- {
- return hdw->control_cnt;
- }
- /* Retrieve a control handle given its index (0..count-1) */
- struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,
- unsigned int idx)
- {
- if (idx >= hdw->control_cnt) return NULL;
- return hdw->controls + idx;
- }
- /* Retrieve a control handle given its index (0..count-1) */
- struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw,
- unsigned int ctl_id)
- {
- struct pvr2_ctrl *cptr;
- unsigned int idx;
- int i;
- /* This could be made a lot more efficient, but for now... */
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- i = cptr->info->internal_id;
- if (i && (i == ctl_id)) return cptr;
- }
- return NULL;
- }
- /* Given a V4L ID, retrieve the control structure associated with it. */
- struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id)
- {
- struct pvr2_ctrl *cptr;
- unsigned int idx;
- int i;
- /* This could be made a lot more efficient, but for now... */
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- i = cptr->info->v4l_id;
- if (i && (i == ctl_id)) return cptr;
- }
- return NULL;
- }
- /* Given a V4L ID for its immediate predecessor, retrieve the control
- structure associated with it. */
- struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw,
- unsigned int ctl_id)
- {
- struct pvr2_ctrl *cptr,*cp2;
- unsigned int idx;
- int i;
- /* This could be made a lot more efficient, but for now... */
- cp2 = NULL;
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- i = cptr->info->v4l_id;
- if (!i) continue;
- if (i <= ctl_id) continue;
- if (cp2 && (cp2->info->v4l_id < i)) continue;
- cp2 = cptr;
- }
- return cp2;
- return NULL;
- }
- static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
- {
- switch (tp) {
- case pvr2_ctl_int: return "integer";
- case pvr2_ctl_enum: return "enum";
- case pvr2_ctl_bool: return "boolean";
- case pvr2_ctl_bitmask: return "bitmask";
- }
- return "";
- }
- /* Commit all control changes made up to this point. Subsystems can be
- indirectly affected by these changes. For a given set of things being
- committed, we'll clear the affected subsystem bits and then once we're
- done committing everything we'll make a request to restore the subsystem
- state(s) back to their previous value before this function was called.
- Thus we can automatically reconfigure affected pieces of the driver as
- controls are changed. */
- static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
- {
- unsigned long saved_subsys_mask = hdw->subsys_enabled_mask;
- unsigned long stale_subsys_mask = 0;
- unsigned int idx;
- struct pvr2_ctrl *cptr;
- int value;
- int commit_flag = 0;
- char buf[100];
- unsigned int bcnt,ccnt;
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- if (cptr->info->is_dirty == 0) continue;
- if (!cptr->info->is_dirty(cptr)) continue;
- if (!commit_flag) {
- commit_flag = !0;
- }
- bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
- cptr->info->name);
- value = 0;
- cptr->info->get_value(cptr,&value);
- pvr2_ctrl_value_to_sym_internal(cptr,~0,value,
- buf+bcnt,
- sizeof(buf)-bcnt,&ccnt);
- bcnt += ccnt;
- bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>",
- get_ctrl_typename(cptr->info->type));
- pvr2_trace(PVR2_TRACE_CTL,
- "/*--TRACE_COMMIT--*/ %.*s",
- bcnt,buf);
- }
- if (!commit_flag) {
- /* Nothing has changed */
- return 0;
- }
- /* When video standard changes, reset the hres and vres values -
- but if the user has pending changes there, then let the changes
- take priority. */
- if (hdw->std_dirty) {
- /* Rewrite the vertical resolution to be appropriate to the
- video standard that has been selected. */
- int nvres;
- if (hdw->std_mask_cur & V4L2_STD_525_60) {
- nvres = 480;
- } else {
- nvres = 576;
- }
- if (nvres != hdw->res_ver_val) {
- hdw->res_ver_val = nvres;
- hdw->res_ver_dirty = !0;
- }
- }
- if (hdw->std_dirty ||
- hdw->enc_stale ||
- hdw->srate_dirty ||
- hdw->res_ver_dirty ||
- hdw->res_hor_dirty ||
- 0) {
- /* If any of this changes, then the encoder needs to be
- reconfigured, and we need to reset the stream. */
- stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
- }
- if (hdw->srate_dirty) {
- /* Write new sample rate into control structure since
- * the master copy is stale. We must track srate
- * separate from the mpeg control structure because
- * other logic also uses this value. */
- struct v4l2_ext_controls cs;
- struct v4l2_ext_control c1;
- memset(&cs,0,sizeof(cs));
- memset(&c1,0,sizeof(c1));
- cs.controls = &c1;
- cs.count = 1;
- c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
- c1.value = hdw->srate_val;
- cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS);
- }
- /* Scan i2c core at this point - before we clear all the dirty
- bits. Various parts of the i2c core will notice dirty bits as
- appropriate and arrange to broadcast or directly send updates to
- the client drivers in order to keep everything in sync */
- pvr2_i2c_core_check_stale(hdw);
- for (idx = 0; idx < hdw->control_cnt; idx++) {
- cptr = hdw->controls + idx;
- if (!cptr->info->clear_dirty) continue;
- cptr->info->clear_dirty(cptr);
- }
- /* Now execute i2c core update */
- pvr2_i2c_core_sync(hdw);
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,stale_subsys_mask,0);
- pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,saved_subsys_mask);
- return 0;
- }
- int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
- {
- LOCK_TAKE(hdw->big_lock); do {
- pvr2_hdw_commit_ctl_internal(hdw);
- } while (0); LOCK_GIVE(hdw->big_lock);
- return 0;
- }
- void pvr2_hdw_poll(struct pvr2_hdw *hdw)
- {
- LOCK_TAKE(hdw->big_lock); do {
- pvr2_i2c_core_sync(hdw);
- } while (0); LOCK_GIVE(hdw->big_lock);
- }
- void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *hdw,
- void (*func)(void *),
- void *data)
- {
- LOCK_TAKE(hdw->big_lock); do {
- hdw->poll_trigger_func = func;
- hdw->poll_trigger_data = data;
- } while (0); LOCK_GIVE(hdw->big_lock);
- }
- void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw)
- {
- if (hdw->poll_trigger_func) {
- hdw->poll_trigger_func(hdw->poll_trigger_data);
- }
- }
- /* Return name for this driver instance */
- const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
- {
- return hdw->name;
- }
- /* Return bit mask indicating signal status */
- static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
- {
- unsigned int msk = 0;
- switch (hdw->input_val) {
- case PVR2_CVAL_INPUT_TV:
- case PVR2_CVAL_INPUT_RADIO:
- if (hdw->decoder_ctrl &&
- hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) {
- msk |= PVR2_SIGNAL_OK;
- if (hdw->audio_stat &&
- hdw->audio_stat->status(hdw->audio_stat->ctxt)) {
- if (hdw->flag_stereo) {
- msk |= PVR2_SIGNAL_STEREO;
- }
- if (hdw->flag_bilingual) {
- msk |= PVR2_SIGNAL_SAP;
- }
- }
- }
- break;
- default:
- msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO;
- }
- return msk;
- }
- int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
- {
- int result;
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = 0x0b;
- result = pvr2_send_request(hdw,
- hdw->cmd_buffer,1,
- hdw->cmd_buffer,1);
- if (result < 0) break;
- result = (hdw->cmd_buffer[0] != 0);
- } while(0); LOCK_GIVE(hdw->ctl_lock);
- return result;
- }
- /* Return bit mask indicating signal status */
- unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
- {
- unsigned int msk = 0;
- LOCK_TAKE(hdw->big_lock); do {
- msk = pvr2_hdw_get_signal_status_internal(hdw);
- } while (0); LOCK_GIVE(hdw->big_lock);
- return msk;
- }
- /* Get handle to video output stream */
- struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
- {
- return hp->vid_stream;
- }
- void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
- {
- int nr = pvr2_hdw_get_unit_number(hdw);
- LOCK_TAKE(hdw->big_lock); do {
- hdw->log_requested = !0;
- printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr);
- pvr2_i2c_core_check_stale(hdw);
- hdw->log_requested = 0;
- pvr2_i2c_core_sync(hdw);
- pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
- cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
- printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr);
- } while (0); LOCK_GIVE(hdw->big_lock);
- }
- void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
- {
- int ret;
- u16 address;
- unsigned int pipe;
- LOCK_TAKE(hdw->big_lock); do {
- if ((hdw->fw_buffer == 0) == !enable_flag) break;
- if (!enable_flag) {
- pvr2_trace(PVR2_TRACE_FIRMWARE,
- "Cleaning up after CPU firmware fetch");
- kfree(hdw->fw_buffer);
- hdw->fw_buffer = NULL;
- hdw->fw_size = 0;
- /* Now release the CPU. It will disconnect and
- reconnect later. */
- pvr2_hdw_cpureset_assert(hdw,0);
- break;
- }
- pvr2_trace(PVR2_TRACE_FIRMWARE,
- "Preparing to suck out CPU firmware");
- hdw->fw_size = 0x2000;
- hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL);
- if (!hdw->fw_buffer) {
- hdw->fw_size = 0;
- break;
- }
- memset(hdw->fw_buffer,0,hdw->fw_size);
- /* We have to hold the CPU during firmware upload. */
- pvr2_hdw_cpureset_assert(hdw,1);
- /* download the firmware from address 0000-1fff in 2048
- (=0x800) bytes chunk. */
- pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware");
- pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
- for(address = 0; address < hdw->fw_size; address += 0x800) {
- ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0,
- address,0,
- hdw->fw_buffer+address,0x800,HZ);
- if (ret < 0) break;
- }
- pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware");
- } while (0); LOCK_GIVE(hdw->big_lock);
- }
- /* Return true if we're in a mode for retrieval CPU firmware */
- int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
- {
- return hdw->fw_buffer != 0;
- }
- int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs,
- char *buf,unsigned int cnt)
- {
- int ret = -EINVAL;
- LOCK_TAKE(hdw->big_lock); do {
- if (!buf) break;
- if (!cnt) break;
- if (!hdw->fw_buffer) {
- ret = -EIO;
- break;
- }
- if (offs >= hdw->fw_size) {
- pvr2_trace(PVR2_TRACE_FIRMWARE,
- "Read firmware data offs=%d EOF",
- offs);
- ret = 0;
- break;
- }
- if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs;
- memcpy(buf,hdw->fw_buffer+offs,cnt);
- pvr2_trace(PVR2_TRACE_FIRMWARE,
- "Read firmware data offs=%d cnt=%d",
- offs,cnt);
- ret = cnt;
- } while (0); LOCK_GIVE(hdw->big_lock);
- return ret;
- }
- int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw)
- {
- return hdw->v4l_minor_number;
- }
- /* Store the v4l minor device number */
- void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
- {
- hdw->v4l_minor_number = v;
- }
- static void pvr2_ctl_write_complete(struct urb *urb)
- {
- struct pvr2_hdw *hdw = urb->context;
- hdw->ctl_write_pend_flag = 0;
- if (hdw->ctl_read_pend_flag) return;
- complete(&hdw->ctl_done);
- }
- static void pvr2_ctl_read_complete(struct urb *urb)
- {
- struct pvr2_hdw *hdw = urb->context;
- hdw->ctl_read_pend_flag = 0;
- if (hdw->ctl_write_pend_flag) return;
- complete(&hdw->ctl_done);
- }
- static void pvr2_ctl_timeout(unsigned long data)
- {
- struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
- if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
- hdw->ctl_timeout_flag = !0;
- if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) {
- usb_unlink_urb(hdw->ctl_write_urb);
- }
- if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
- usb_unlink_urb(hdw->ctl_read_urb);
- }
- }
- }
- /* Issue a command and get a response from the device. This extended
- version includes a probe flag (which if set means that device errors
- should not be logged or treated as fatal) and a timeout in jiffies.
- This can be used to non-lethally probe the health of endpoint 1. */
- static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
- unsigned int timeout,int probe_fl,
- void *write_data,unsigned int write_len,
- void *read_data,unsigned int read_len)
- {
- unsigned int idx;
- int status = 0;
- struct timer_list timer;
- if (!hdw->ctl_lock_held) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute control transfer"
- " without lock!!");
- return -EDEADLK;
- }
- if ((!hdw->flag_ok) && !probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute control transfer"
- " when device not ok");
- return -EIO;
- }
- if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
- if (!probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute control transfer"
- " when USB is disconnected");
- }
- return -ENOTTY;
- }
- /* Ensure that we have sane parameters */
- if (!write_data) write_len = 0;
- if (!read_data) read_len = 0;
- if (write_len > PVR2_CTL_BUFFSIZE) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute %d byte"
- " control-write transfer (limit=%d)",
- write_len,PVR2_CTL_BUFFSIZE);
- return -EINVAL;
- }
- if (read_len > PVR2_CTL_BUFFSIZE) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute %d byte"
- " control-read transfer (limit=%d)",
- write_len,PVR2_CTL_BUFFSIZE);
- return -EINVAL;
- }
- if ((!write_len) && (!read_len)) {
- pvr2_trace(
- PVR2_TRACE_ERROR_LEGS,
- "Attempted to execute null control transfer?");
- return -EINVAL;
- }
- hdw->cmd_debug_state = 1;
- if (write_len) {
- hdw->cmd_debug_code = ((unsigned char *)write_data)[0];
- } else {
- hdw->cmd_debug_code = 0;
- }
- hdw->cmd_debug_write_len = write_len;
- hdw->cmd_debug_read_len = read_len;
- /* Initialize common stuff */
- init_completion(&hdw->ctl_done);
- hdw->ctl_timeout_flag = 0;
- hdw->ctl_write_pend_flag = 0;
- hdw->ctl_read_pend_flag = 0;
- init_timer(&timer);
- timer.expires = jiffies + timeout;
- timer.data = (unsigned long)hdw;
- timer.function = pvr2_ctl_timeout;
- if (write_len) {
- hdw->cmd_debug_state = 2;
- /* Transfer write data to internal buffer */
- for (idx = 0; idx < write_len; idx++) {
- hdw->ctl_write_buffer[idx] =
- ((unsigned char *)write_data)[idx];
- }
- /* Initiate a write request */
- usb_fill_bulk_urb(hdw->ctl_write_urb,
- hdw->usb_dev,
- usb_sndbulkpipe(hdw->usb_dev,
- PVR2_CTL_WRITE_ENDPOINT),
- hdw->ctl_write_buffer,
- write_len,
- pvr2_ctl_write_complete,
- hdw);
- hdw->ctl_write_urb->actual_length = 0;
- hdw->ctl_write_pend_flag = !0;
- status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL);
- if (status < 0) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failed to submit write-control"
- " URB status=%d",status);
- hdw->ctl_write_pend_flag = 0;
- goto done;
- }
- }
- if (read_len) {
- hdw->cmd_debug_state = 3;
- memset(hdw->ctl_read_buffer,0x43,read_len);
- /* Initiate a read request */
- usb_fill_bulk_urb(hdw->ctl_read_urb,
- hdw->usb_dev,
- usb_rcvbulkpipe(hdw->usb_dev,
- PVR2_CTL_READ_ENDPOINT),
- hdw->ctl_read_buffer,
- read_len,
- pvr2_ctl_read_complete,
- hdw);
- hdw->ctl_read_urb->actual_length = 0;
- hdw->ctl_read_pend_flag = !0;
- status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL);
- if (status < 0) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failed to submit read-control"
- " URB status=%d",status);
- hdw->ctl_read_pend_flag = 0;
- goto done;
- }
- }
- /* Start timer */
- add_timer(&timer);
- /* Now wait for all I/O to complete */
- hdw->cmd_debug_state = 4;
- while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
- wait_for_completion(&hdw->ctl_done);
- }
- hdw->cmd_debug_state = 5;
- /* Stop timer */
- del_timer_sync(&timer);
- hdw->cmd_debug_state = 6;
- status = 0;
- if (hdw->ctl_timeout_flag) {
- status = -ETIMEDOUT;
- if (!probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Timed out control-write");
- }
- goto done;
- }
- if (write_len) {
- /* Validate results of write request */
- if ((hdw->ctl_write_urb->status != 0) &&
- (hdw->ctl_write_urb->status != -ENOENT) &&
- (hdw->ctl_write_urb->status != -ESHUTDOWN) &&
- (hdw->ctl_write_urb->status != -ECONNRESET)) {
- /* USB subsystem is reporting some kind of failure
- on the write */
- status = hdw->ctl_write_urb->status;
- if (!probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-write URB failure,"
- " status=%d",
- status);
- }
- goto done;
- }
- if (hdw->ctl_write_urb->actual_length < write_len) {
- /* Failed to write enough data */
- status = -EIO;
- if (!probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-write URB short,"
- " expected=%d got=%d",
- write_len,
- hdw->ctl_write_urb->actual_length);
- }
- goto done;
- }
- }
- if (read_len) {
- /* Validate results of read request */
- if ((hdw->ctl_read_urb->status != 0) &&
- (hdw->ctl_read_urb->status != -ENOENT) &&
- (hdw->ctl_read_urb->status != -ESHUTDOWN) &&
- (hdw->ctl_read_urb->status != -ECONNRESET)) {
- /* USB subsystem is reporting some kind of failure
- on the read */
- status = hdw->ctl_read_urb->status;
- if (!probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-read URB failure,"
- " status=%d",
- status);
- }
- goto done;
- }
- if (hdw->ctl_read_urb->actual_length < read_len) {
- /* Failed to read enough data */
- status = -EIO;
- if (!probe_fl) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "control-read URB short,"
- " expected=%d got=%d",
- read_len,
- hdw->ctl_read_urb->actual_length);
- }
- goto done;
- }
- /* Transfer retrieved data out from internal buffer */
- for (idx = 0; idx < read_len; idx++) {
- ((unsigned char *)read_data)[idx] =
- hdw->ctl_read_buffer[idx];
- }
- }
- done:
- hdw->cmd_debug_state = 0;
- if ((status < 0) && (!probe_fl)) {
- pvr2_hdw_render_useless_unlocked(hdw);
- }
- return status;
- }
- int pvr2_send_request(struct pvr2_hdw *hdw,
- void *write_data,unsigned int write_len,
- void *read_data,unsigned int read_len)
- {
- return pvr2_send_request_ex(hdw,HZ*4,0,
- write_data,write_len,
- read_data,read_len);
- }
- int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
- {
- int ret;
- LOCK_TAKE(hdw->ctl_lock);
- hdw->cmd_buffer[0] = 0x04; /* write register prefix */
- PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
- hdw->cmd_buffer[5] = 0;
- hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
- hdw->cmd_buffer[7] = reg & 0xff;
- ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0);
- LOCK_GIVE(hdw->ctl_lock);
- return ret;
- }
- static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
- {
- int ret = 0;
- LOCK_TAKE(hdw->ctl_lock);
- hdw->cmd_buffer[0] = 0x05; /* read register prefix */
- hdw->cmd_buffer[1] = 0;
- hdw->cmd_buffer[2] = 0;
- hdw->cmd_buffer[3] = 0;
- hdw->cmd_buffer[4] = 0;
- hdw->cmd_buffer[5] = 0;
- hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
- hdw->cmd_buffer[7] = reg & 0xff;
- ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4);
- *data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0);
- LOCK_GIVE(hdw->ctl_lock);
- return ret;
- }
- static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
- {
- int ret;
- LOCK_TAKE(hdw->ctl_lock);
- hdw->cmd_buffer[0] = (data >> 8) & 0xff;
- hdw->cmd_buffer[1] = data & 0xff;
- ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res);
- LOCK_GIVE(hdw->ctl_lock);
- return ret;
- }
- static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
- {
- int ret;
- LOCK_TAKE(hdw->ctl_lock);
- hdw->cmd_buffer[0] = data;
- ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res);
- LOCK_GIVE(hdw->ctl_lock);
- return ret;
- }
- static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
- {
- if (!hdw->flag_ok) return;
- pvr2_trace(PVR2_TRACE_INIT,"render_useless");
- hdw->flag_ok = 0;
- if (hdw->vid_stream) {
- pvr2_stream_setup(hdw->vid_stream,NULL,0,0);
- }
- hdw->flag_streaming_enabled = 0;
- hdw->subsys_enabled_mask = 0;
- }
- void pvr2_hdw_render_useless(struct pvr2_hdw *hdw)
- {
- LOCK_TAKE(hdw->ctl_lock);
- pvr2_hdw_render_useless_unlocked(hdw);
- LOCK_GIVE(hdw->ctl_lock);
- }
- void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
- {
- int ret;
- pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
- ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
- if (ret == 1) {
- ret = usb_reset_device(hdw->usb_dev);
- usb_unlock_device(hdw->usb_dev);
- } else {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "Failed to lock USB device ret=%d",ret);
- }
- if (init_pause_msec) {
- pvr2_trace(PVR2_TRACE_INFO,
- "Waiting %u msec for hardware to settle",
- init_pause_msec);
- msleep(init_pause_msec);
- }
- }
- void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
- {
- char da[1];
- unsigned int pipe;
- int ret;
- if (!hdw->usb_dev) return;
- pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
- da[0] = val ? 0x01 : 0x00;
- /* Write the CPUCS register on the 8051. The lsb of the register
- is the reset bit; a 1 asserts reset while a 0 clears it. */
- pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
- ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ);
- if (ret < 0) {
- pvr2_trace(PVR2_TRACE_ERROR_LEGS,
- "cpureset_assert(%d) error=%d",val,ret);
- pvr2_hdw_render_useless(hdw);
- }
- }
- int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
- {
- int status;
- LOCK_TAKE(hdw->ctl_lock); do {
- pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
- hdw->flag_ok = !0;
- hdw->cmd_buffer[0] = 0xdd;
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- return status;
- }
- int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
- {
- int status;
- LOCK_TAKE(hdw->ctl_lock); do {
- pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
- hdw->cmd_buffer[0] = 0xde;
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- return status;
- }
- int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
- {
- if (!hdw->decoder_ctrl) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Unable to reset decoder: nothing attached");
- return -ENOTTY;
- }
- if (!hdw->decoder_ctrl->force_reset) {
- pvr2_trace(PVR2_TRACE_INIT,
- "Unable to reset decoder: not implemented");
- return -ENOTTY;
- }
- pvr2_trace(PVR2_TRACE_INIT,
- "Requesting decoder reset");
- hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt);
- return 0;
- }
- /* Stop / start video stream transport */
- static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
- {
- int status;
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37);
- status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0);
- } while (0); LOCK_GIVE(hdw->ctl_lock);
- if (!status) {
- hdw->subsys_enabled_mask =
- ((hdw->subsys_enabled_mask &
- ~(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) |
- (runFl ? (1<<PVR2_SUBSYS_B_USBSTREAM_RUN) : 0));
- }
- return status;
- }
- void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw,
- struct pvr2_hdw_debug_info *ptr)
- {
- ptr->big_lock_held = hdw->big_lock_held;
- ptr->ctl_lock_held = hdw->ctl_lock_held;
- ptr->flag_ok = hdw->flag_ok;
- ptr->flag_disconnected = hdw->flag_disconnected;
- ptr->flag_init_ok = hdw->flag_init_ok;
- ptr->flag_streaming_enabled = hdw->flag_streaming_enabled;
- ptr->subsys_flags = hdw->subsys_enabled_mask;
- ptr->cmd_debug_state = hdw->cmd_debug_state;
- ptr->cmd_code = hdw->cmd_debug_code;
- ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
- ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
- ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
- ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
- ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
- ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
- ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
- }
- int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
- {
- return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
- }
- int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp)
- {
- return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp);
- }
- int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp)
- {
- return pvr2_read_register(hdw,PVR2_GPIO_IN,dp);
- }
- int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val)
- {
- u32 cval,nval;
- int ret;
- if (~msk) {
- ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval);
- if (ret) return ret;
- nval = (cval & ~msk) | (val & msk);
- pvr2_trace(PVR2_TRACE_GPIO,
- "GPIO direction changing 0x%x:0x%x"
- " from 0x%x to 0x%x",
- msk,val,cval,nval);
- } else {
- nval = val;
- pvr2_trace(PVR2_TRACE_GPIO,
- "GPIO direction changing to 0x%x",nval);
- }
- return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval);
- }
- int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
- {
- u32 cval,nval;
- int ret;
- if (~msk) {
- ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval);
- if (ret) return ret;
- nval = (cval & ~msk) | (val & msk);
- pvr2_trace(PVR2_TRACE_GPIO,
- "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x",
- msk,val,cval,nval);
- } else {
- nval = val;
- pvr2_trace(PVR2_TRACE_GPIO,
- "GPIO output changing to 0x%x",nval);
- }
- return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval);
- }
- /* Find I2C address of eeprom */
- static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
- {
- int result;
- LOCK_TAKE(hdw->ctl_lock); do {
- hdw->cmd_buffer[0] = 0xeb;
- result = pvr2_send_request(hdw,
- hdw->cmd_buffer,1,
- hdw->cmd_buffer,1);
- if (result < 0) break;
- result = hdw->cmd_buffer[0];
- } while(0); LOCK_GIVE(hdw->ctl_lock);
- return result;
- }
- int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
- u32 chip_id,unsigned long reg_id,
- int setFl,u32 *val_ptr)
- {
- #ifdef CONFIG_VIDEO_ADV_DEBUG
- struct list_head *item;
- struct pvr2_i2c_client *cp;
- struct v4l2_register req;
- int stat = 0;
- int okFl = 0;
- req.i2c_id = chip_id;
- req.reg = reg_id;
- if (setFl) req.val = *val_ptr;
- mutex_lock(&hdw->i2c_list_lock); do {
- list_for_each(item,&hdw->i2c_clients) {
- cp = list_entry(item,struct pvr2_i2c_client,list);
- if (cp->client->driver->id != chip_id) continue;
- stat = pvr2_i2c_client_cmd(
- cp,(setFl ? VIDIOC_INT_S_REGISTER :
- VIDIOC_INT_G_REGISTER),&req);
- if (!setFl) *val_ptr = req.val;
- okFl = !0;
- break;
- }
- } while (0); mutex_unlock(&hdw->i2c_list_lock);
- if (okFl) {
- return stat;
- }
- return -EINVAL;
- #else
- return -ENOSYS;
- #endif
- }
- /*
- Stuff for Emacs to see, in order to encourage consistent editing style:
- *** Local Variables: ***
- *** mode: c ***
- *** fill-column: 75 ***
- *** tab-width: 8 ***
- *** c-basic-offset: 8 ***
- *** End: ***
- */
|