devtv.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202
  1. /*
  2. * Driver for Bt848 TV tuner.
  3. *
  4. */
  5. #include "u.h"
  6. #include "../port/lib.h"
  7. #include "mem.h"
  8. #include "dat.h"
  9. #include "fns.h"
  10. #include "../port/error.h"
  11. #include "io.h"
  12. #include "hcwAMC.h"
  13. #define max(a, b) (((a) > (b))? (a): (b))
  14. enum {
  15. Qdir = 0,
  16. Qsubdir,
  17. Qsubbase,
  18. Qvdata = Qsubbase,
  19. Qadata,
  20. Qctl,
  21. Qregs,
  22. Brooktree_vid = 0x109e,
  23. Brooktree_848_did = 0x0350,
  24. Brooktree_878_did = 0x036E,
  25. Intel_vid = 0x8086,
  26. Intel_82437_did = 0x122d,
  27. K = 1024,
  28. M = K * K,
  29. Ntvs = 4,
  30. Numring = 16,
  31. ntsc_rawpixels = 910,
  32. ntsc_sqpixels = 780, // Including blanking & inactive
  33. ntsc_hactive = 640,
  34. ntsc_vactive = 480,
  35. ntsc_clkx1delay = 135, // Clock ticks.
  36. ntsc_clkx1hactive = 754,
  37. ntsc_vdelay = 26, // # of scan lines.
  38. ntsc_vscale = 0,
  39. i2c_nostop = 1 << 5,
  40. i2c_nos1b = 1 << 4,
  41. i2c_timing = 7 << 4,
  42. i2c_bt848w3b = 1 << 2,
  43. i2c_bt848scl = 1 << 1,
  44. i2c_bt848sda = 1 << 0,
  45. i2c_scl = i2c_bt848scl,
  46. i2c_sda = i2c_bt848sda,
  47. i2c_miroproee = 0x80, // MIRO PRO EEPROM
  48. i2c_tea6300 = 0x80,
  49. i2c_tda8425 = 0x82,
  50. i2c_tda9840 = 0x84,
  51. i2c_tda9850 = 0xb6,
  52. i2c_haupee = 0xa0, // Hauppage EEPROM
  53. i2c_stbee = 0xae, // STB EEPROM
  54. i2c_msp3400 = 0x80,
  55. i2c_timeout = 1000,
  56. i2c_delay = 10,
  57. Bt848_miropro = 0,
  58. Bt848_miro,
  59. Bt878_hauppauge,
  60. // Bit fields.
  61. iform_muxsel1 = 3 << 5, // 004
  62. iform_muxsel0 = 2 << 5,
  63. iform_xtselmask = 3 << 3,
  64. iform_xtauto = 3 << 3,
  65. iform_formatmask = 7 << 0,
  66. iform_ntsc = 1 << 0,
  67. control_ldec = 1 << 5, // 02C
  68. contrast_100percent = 0xd8, // 030
  69. vscale_interlaced = 1 << 5, // 04C
  70. adelay_ntsc = 104, // 060
  71. bdelay_ntsc = 93, // 064
  72. adc_crush = 1 << 0, // 068
  73. colorfmt_rgb16 = (2 << 4) | (2 << 0), // 0D4
  74. colorfmt_YCbCr422 = (8 << 4) | (8 << 0),
  75. colorfmt_YCbCr411 = (9 << 4) | (9 << 0),
  76. colorctl_gamma = 1 << 4, // 0D8
  77. capctl_fullframe = 1 << 4, // 0DC
  78. capctl_captureodd = 1 << 1,
  79. capctl_captureeven = 1 << 0,
  80. vbipacksize = 0x190, // 0E0
  81. intstat_riscstatshift = 28, // 100
  82. intstat_i2crack = 1 << 25,
  83. intstat_scerr = 1 << 19,
  84. intstat_ocerr = 1 << 18,
  85. intstat_pabort = 1 << 17,
  86. intstat_riperr = 1 << 16,
  87. intstat_pperr = 1 << 15,
  88. intstat_fdsr = 1 << 14,
  89. intstat_ftrgt = 1 << 13,
  90. intstat_fbus = 1 << 12,
  91. intstat_risci = 1 << 11,
  92. intstat_i2cdone = 1 << 8,
  93. intstat_vpress = 1 << 5,
  94. intstat_hlock = 1 << 4,
  95. intstat_vsync = 1 << 1,
  96. intstat_fmtchg = 1 << 0,
  97. intmask_etbf = 1 << 23, // 104
  98. gpiodmactl_apwrdn = 1 << 26, // 10C
  99. gpiodmactl_daes2 = 1 << 13,
  100. gpiodmactl_daiomda = 1 << 6,
  101. gpiodmactl_pltp23_16 = 2 << 6,
  102. gpiodmactl_pltp23_0 = 0 << 6,
  103. gpiodmactl_pltp1_16 = 2 << 4,
  104. gpiodmactl_pltp1_0 = 0 << 4,
  105. gpiodmactl_acapenable = 1 << 4,
  106. gpiodmactl_pktp_32 = 3 << 2,
  107. gpiodmactl_pktp_0 = 0 << 2,
  108. gpiodmactl_riscenable = 1 << 1,
  109. gpiodmactl_fifoenable = 1 << 0,
  110. // RISC instructions and parameters.
  111. fifo_vre = 0x4,
  112. fifo_vro = 0xc,
  113. fifo_fm1 = 0x6,
  114. fifo_fm3 = 0xe,
  115. riscirq = 1 << 24,
  116. riscwrite = 1 << 28,
  117. riscwrite123 = 9 << 28,
  118. riscwrite1s23 = 11 << 28,
  119. riscwrite_sol = 1 << 27,
  120. riscwrite_eol = 1 << 26,
  121. riscskip = 0x2 << 28,
  122. riscjmp = 0x7 << 28,
  123. riscsync = 0x8 << 28,
  124. riscsync_resync = 1 << 15,
  125. riscsync_vre = fifo_vre << 0,
  126. riscsync_vro = fifo_vro << 0,
  127. riscsync_fm1 = fifo_fm1 << 0,
  128. riscsync_fm3 = fifo_fm3 << 0,
  129. risclabelshift_set = 16,
  130. risclabelshift_reset = 20,
  131. AudioTuner = 0,
  132. AudioRadio,
  133. AudioExtern,
  134. AudioIntern,
  135. AudioOff,
  136. AudioOn,
  137. asel_tv = 0,
  138. asel_radio,
  139. asel_mic,
  140. asel_smxc,
  141. Hwbase_ad = 448000,
  142. msp_dem = 0x10,
  143. msp_bbp = 0x12,
  144. // Altera definitions.
  145. gpio_altera_data = 1 << 0,
  146. gpio_altera_clock = 1 << 20,
  147. gpio_altera_nconfig = 1 << 23,
  148. Ial = 0x140001,
  149. Idma = 0x100002,
  150. Adsp = 0x7fd8,
  151. Adsp_verifysystem = 1,
  152. Adsp_querysupportplay,
  153. Adsp_setstyle,
  154. Adsp_setsrate,
  155. Adsp_setchannels,
  156. Adsp_setresolution,
  157. Adsp_setcrcoptions,
  158. Adsp_bufenqfor,
  159. Adsp_logbuffer,
  160. Adsp_startplay,
  161. Adsp_stopplay,
  162. Adsp_autostop,
  163. Adsp_startrecord,
  164. Adsp_stoprecord,
  165. Adsp_getlastprocessed,
  166. Adsp_pause,
  167. Adsp_resume,
  168. Adsp_setvolume,
  169. Adsp_querysupportrecord,
  170. Adsp_generalbufenq,
  171. Adsp_setdownmixtype,
  172. Adsp_setigain,
  173. Adsp_setlineout,
  174. Adsp_setlangmixtype,
  175. Kfir_gc = 0,
  176. Kfir_dsp_riscmc,
  177. Kfir_dsp_risccram,
  178. Kfir_dsp_unitmc,
  179. Kfir_bsm_mc,
  180. Kfir_mux_mc,
  181. Kfir_devid_gc = 7,
  182. Kfir_devid_dsp = 4,
  183. Kfir_devid_bsm = 5,
  184. Kfir_devid_mux = 8,
  185. Kfir_200 = 200,
  186. Kfir_dev_inst = Kfir_200,
  187. Kfir_201 = 201,
  188. Kfir_exec = Kfir_201,
  189. Kfir_202 = 202,
  190. Kfir_adr_eready = 254,
  191. Kfir_d_eready_encoding = 0,
  192. Kfir_d_eready_ready,
  193. Kfir_d_eready_test,
  194. Kfir_d_eready_stopdetect,
  195. Kfir_d_eready_seqend,
  196. VT_KFIR_OFF = 0,
  197. VT_KFIR_ON,
  198. VT_KFIR_LAYER_II = 1,
  199. VT_KFIR_STEREO = 1,
  200. Gpioinit = 0,
  201. Gpiooutput,
  202. Gpioinput,
  203. Srate_5512 = 0,
  204. Srate_11025 = 2,
  205. Srate_16000 = 3,
  206. Srate_22050 = 4,
  207. Srate_32000 = 5,
  208. Srate_44100 = 6,
  209. Srate_48000 = 7,
  210. };
  211. typedef struct Variant Variant;
  212. struct Variant {
  213. ushort vid;
  214. ushort did;
  215. char *name;
  216. };
  217. typedef struct Bt848 Bt848;
  218. struct Bt848 {
  219. ulong devstat; // 000
  220. ulong iform; // 004
  221. ulong tdec; // 008
  222. ulong ecrop; // 00C
  223. ulong evdelaylo; // 010
  224. ulong evactivelo; // 014
  225. ulong ehdelaylo; // 018
  226. ulong ehactivelo; // 01C
  227. ulong ehscalehi; // 020
  228. ulong ehscalelo; // 024
  229. ulong bright; // 028
  230. ulong econtrol; // 02C
  231. ulong contrastlo; // 030
  232. ulong satulo; // 034
  233. ulong satvlo; // 038
  234. ulong hue; // 03C
  235. ulong escloop; // 040
  236. ulong pad0; // 044
  237. ulong oform; // 048
  238. ulong evscalehi; // 04C
  239. ulong evscalelo; // 050
  240. ulong test; // 054
  241. ulong pad1[2]; // 058-05C
  242. ulong adelay; // 060
  243. ulong bdelay; // 064
  244. ulong adc; // 068
  245. ulong evtc; // 06C
  246. ulong pad2[3]; // 070-078
  247. ulong sreset; // 07C
  248. ulong tglb; // 080
  249. ulong tgctrl; // 084
  250. ulong pad3; // 088
  251. ulong ocrop; // 08C
  252. ulong ovdelaylo; // 090
  253. ulong ovactivelo; // 094
  254. ulong ohdelaylo; // 098
  255. ulong ohactivelo; // 09C
  256. ulong ohscalehi; // 0A0
  257. ulong ohscalelo; // 0A4
  258. ulong pad4; // 0A8
  259. ulong ocontrol; // 0AC
  260. ulong pad5[4]; // 0B0-0BC
  261. ulong oscloop; // 0C0
  262. ulong pad6[2]; // 0C4-0C8
  263. ulong ovscalehi; // 0CC
  264. ulong ovscalelo; // 0D0
  265. ulong colorfmt; // 0D4
  266. ulong colorctl; // 0D8
  267. ulong capctl; // 0DC
  268. ulong vbipacksize; // 0E0
  269. ulong vbipackdel; // 0E4
  270. ulong fcap; // 0E8
  271. ulong ovtc; // 0EC
  272. ulong pllflo; // 0F0
  273. ulong pllfhi; // 0F4
  274. ulong pllxci; // 0F8
  275. ulong dvsif; // 0FC
  276. ulong intstat; // 100
  277. ulong intmask; // 104
  278. ulong pad7; // 108
  279. ulong gpiodmactl; // 10C
  280. ulong i2c; // 110
  281. ulong riscstrtadd; // 114
  282. ulong gpioouten; // 118
  283. ulong gpioreginp; // 11C
  284. ulong risccount; // 120
  285. ulong pad8[55]; // 124-1FC
  286. ulong gpiodata[64]; // 200-2FC
  287. };
  288. #define packetlen i2c
  289. typedef struct Tuner Tuner;
  290. struct Tuner {
  291. char *name;
  292. ushort freq_vhfh; // Start frequency
  293. ushort freq_uhf;
  294. uchar VHF_L;
  295. uchar VHF_H;
  296. uchar UHF;
  297. uchar cfg;
  298. ushort offs;
  299. };
  300. typedef struct Frame Frame;
  301. struct Frame {
  302. ulong *fstart;
  303. ulong *fjmp;
  304. uchar *fbase;
  305. };
  306. typedef struct Tv Tv;
  307. struct Tv {
  308. Lock;
  309. Rendez;
  310. Bt848 *bt848;
  311. Bt848 *bt878; // Really only audio control registers
  312. Variant *variant;
  313. Tuner *tuner;
  314. Pcidev *pci;
  315. uchar i2ctuneraddr;
  316. uchar i2ccmd; // I2C command
  317. int board; // What board is this?
  318. ulong cfmt; // Current color format.
  319. int channel; // Current channel
  320. Ref fref; // Copying images?
  321. int nframes; // Number of frames to capture.
  322. Frame *frames; // DMA program
  323. int lvframe; // Last video frame DMAed
  324. uchar *amux; // Audio multiplexer.
  325. int nablocks; // Number of audio blocks allocated
  326. int absize; // Audio block size
  327. int narblocks; // Number of audio blocks received
  328. ulong *arisc; // Audio risc bloc
  329. uchar *abuf; // Audio data buffers
  330. char ainfo[128];
  331. // WinTV/PVR stuff.
  332. int msp;
  333. Lock kfirlock;
  334. ulong i2cstate; // Last i2c state.
  335. int gpiostate; // Current GPIO state
  336. ulong alterareg; // Last used altera register
  337. ulong alteraclock; // Used to clock the altera
  338. int asrate; // Audio sample rate
  339. uchar aleft, aright; // Left and right audio volume
  340. ulong kfirclock;
  341. Ref aref; // Copying audio?
  342. };
  343. enum {
  344. TemicPAL = 0,
  345. PhilipsPAL,
  346. PhilipsNTSC,
  347. PhilipsSECAM,
  348. Notuner,
  349. PhilipsPALI,
  350. TemicNTSC,
  351. TemicPALI,
  352. Temic4036,
  353. AlpsTSBH1,
  354. AlpsTSBE1,
  355. Freqmultiplier = 16,
  356. };
  357. static Tuner tuners[] = {
  358. {"Temic PAL", Freqmultiplier * 140.25, Freqmultiplier * 463.25,
  359. 0x02, 0x04, 0x01, 0x8e, 623 },
  360. {"Philips PAL_I", Freqmultiplier * 140.25, Freqmultiplier * 463.25,
  361. 0xa0, 0x90, 0x30, 0x8e, 623 },
  362. {"Philips NTSC", Freqmultiplier * 157.25, Freqmultiplier * 451.25,
  363. 0xA0, 0x90, 0x30, 0x8e, 732 },
  364. {"Philips SECAM", Freqmultiplier * 168.25, Freqmultiplier * 447.25,
  365. 0xA7, 0x97, 0x37, 0x8e, 623 },
  366. {"NoTuner", 0, 0,
  367. 0x00, 0x00, 0x00, 0x00, 0 },
  368. {"Philips PAL", Freqmultiplier * 168.25, Freqmultiplier * 447.25,
  369. 0xA0, 0x90, 0x30, 0x8e, 623 },
  370. {"Temic NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,
  371. 0x02, 0x04, 0x01, 0x8e, 732 },
  372. {"TEMIC PAL_I", Freqmultiplier * 170.00, Freqmultiplier * 450.00,
  373. 0x02, 0x04, 0x01, 0x8e, 623 },
  374. {"Temic 4036 FY5 NTSC", Freqmultiplier * 157.25, Freqmultiplier * 463.25,
  375. 0xa0, 0x90, 0x30, 0x8e, 732 },
  376. {"Alps TSBH1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,
  377. 0x01, 0x02, 0x08, 0x8e, 732 },
  378. {"Alps TSBE1", Freqmultiplier * 137.25, Freqmultiplier * 385.25,
  379. 0x01, 0x02, 0x08, 0x8e, 732 },
  380. };
  381. static int hp_tuners[] = {
  382. Notuner,
  383. Notuner,
  384. Notuner,
  385. Notuner,
  386. Notuner,
  387. PhilipsNTSC,
  388. Notuner,
  389. Notuner,
  390. PhilipsPAL,
  391. PhilipsSECAM,
  392. PhilipsNTSC,
  393. PhilipsPALI,
  394. Notuner,
  395. Notuner,
  396. TemicPAL,
  397. TemicPALI,
  398. Notuner,
  399. PhilipsSECAM,
  400. PhilipsNTSC,
  401. PhilipsPALI,
  402. Notuner,
  403. PhilipsPAL,
  404. Notuner,
  405. PhilipsNTSC,
  406. };
  407. enum {
  408. CMvstart,
  409. CMastart,
  410. CMastop,
  411. CMvgastart,
  412. CMvstop,
  413. CMchannel,
  414. CMcolormode,
  415. CMvolume,
  416. CMmute,
  417. };
  418. static Cmdtab tvctlmsg[] = {
  419. CMvstart, "vstart", 2,
  420. CMastart, "astart", 5,
  421. CMastop, "astop", 1,
  422. CMvgastart, "vgastart", 3,
  423. CMvstop, "vstop", 1,
  424. CMchannel, "channel", 3,
  425. CMcolormode, "colormode", 2,
  426. CMvolume, "volume", 3,
  427. CMmute, "mute", 1,
  428. };
  429. static Variant variant[] = {
  430. { Brooktree_vid, Brooktree_848_did, "Brooktree 848 TV tuner", },
  431. { Brooktree_vid, Brooktree_878_did, "Brooktree 878 TV tuner", },
  432. };
  433. static char *boards[] = {
  434. "MIRO PRO",
  435. "MIRO",
  436. "Hauppauge Bt878",
  437. };
  438. static ushort Adspfsample[] = {
  439. 0x500, 0x700, 0x400, 0x600, 0x300, 0x200, 0x000, 0x100
  440. };
  441. static ushort Adspstereorates[] = {
  442. 64, 96, 112, 128, 160, 192, 224, 256, 320, 384
  443. };
  444. static uchar miroamux[] = { 2, 0, 0, 0, 10, 0 };
  445. static uchar hauppaugeamux[] = { 0, 1, 2, 3, 4, 0 };
  446. static char *nicamstate[] = {
  447. "analog", "???", "digital", "bad digital receiption"
  448. };
  449. static Tv tvs[Ntvs];
  450. static int ntvs;
  451. static int i2cread(Tv *, uchar, uchar *);
  452. static int i2cwrite(Tv *, uchar, uchar, uchar, int);
  453. static void tvinterrupt(Ureg *, Tv *);
  454. static void vgastart(Tv *, ulong, int);
  455. static void vstart(Tv *, int, int, int, int);
  456. static void astart(Tv *, char *, uint, uint, uint);
  457. static void vstop(Tv *);
  458. static void astop(Tv *);
  459. static void colormode(Tv *, char *);
  460. static void frequency(Tv *, int, int);
  461. static int getbitspp(Tv *);
  462. static char *getcolormode(ulong);
  463. static int mspreset(Tv *);
  464. static void i2cscan(Tv *);
  465. static int kfirinitialize(Tv *);
  466. static void msptune(Tv *);
  467. static void mspvolume(Tv *, int, int, int);
  468. static void gpioenable(Tv *, ulong, ulong);
  469. static void gpiowrite(Tv *, ulong, ulong);
  470. static void
  471. tvinit(void)
  472. {
  473. Pcidev *pci;
  474. ulong intmask;
  475. // Test for a triton memory controller.
  476. intmask = 0;
  477. if (pcimatch(nil, Intel_vid, Intel_82437_did))
  478. intmask = intmask_etbf;
  479. pci = nil;
  480. while ((pci = pcimatch(pci, 0, 0)) != nil) {
  481. int i, t;
  482. Tv *tv;
  483. Bt848 *bt848;
  484. ushort hscale, hdelay;
  485. uchar v;
  486. for (i = 0; i != nelem(variant); i++)
  487. if (pci->vid == variant[i].vid && pci->did == variant[i].did)
  488. break;
  489. if (i == nelem(variant))
  490. continue;
  491. if (ntvs >= Ntvs) {
  492. print("#V: Too many TV cards found\n");
  493. continue;
  494. }
  495. tv = &tvs[ntvs++];
  496. tv->variant = &variant[i];
  497. tv->pci = pci;
  498. tv->bt848 = (Bt848 *)vmap(pci->mem[0].bar & ~0x0F, 4 * K);
  499. if (tv->bt848 == nil)
  500. panic("#V: Cannot allocate memory for Bt848");
  501. bt848 = tv->bt848;
  502. // i2c stuff.
  503. if (pci->did >= 878)
  504. tv->i2ccmd = 0x83;
  505. else
  506. tv->i2ccmd = i2c_timing | i2c_bt848scl | i2c_bt848sda;
  507. t = 0;
  508. if (i2cread(tv, i2c_haupee, &v)) {
  509. uchar ee[256];
  510. Pcidev *pci878;
  511. Bt848 *bt878;
  512. tv->board = Bt878_hauppauge;
  513. if (!i2cwrite(tv, i2c_haupee, 0, 0, 0))
  514. panic("#V: Cannot write to Hauppauge EEPROM");
  515. for (i = 0; i != sizeof ee; i++)
  516. if (!i2cread(tv, i2c_haupee + 1, &ee[i]))
  517. panic("#V: Cannot read from Hauppauge EEPROM");
  518. if (ee[9] > sizeof hp_tuners / sizeof hp_tuners[0])
  519. panic("#V: Tuner out of range (max %d, this %d)",
  520. sizeof hp_tuners / sizeof hp_tuners[0], ee[9]);
  521. t = hp_tuners[ee[9]];
  522. // Initialize the audio channel.
  523. if ((pci878 = pcimatch(nil, Brooktree_vid, 0x878)) == nil)
  524. panic("#V: Unsupported Hauppage board");
  525. tv->bt878 = bt878 =
  526. (Bt848 *)vmap(pci878->mem[0].bar & ~0x0F, 4 * K);
  527. if (bt878 == nil)
  528. panic("#V: Cannot allocate memory for the Bt878");
  529. kfirinitialize(tv);
  530. // i2cscan(tv);
  531. mspreset(tv);
  532. bt878->gpiodmactl = 0;
  533. bt878->intstat = (ulong)-1;
  534. intrenable(pci878->intl, (void (*)(Ureg *, void *))tvinterrupt,
  535. tv, pci878->tbdf, "tv");
  536. tv->amux = hauppaugeamux;
  537. }
  538. else if (i2cread(tv, i2c_stbee, &v)) {
  539. USED(t);
  540. panic("#V: Cannot deal with STB cards\n");
  541. }
  542. else if (i2cread(tv, i2c_miroproee, &v)) {
  543. tv->board = Bt848_miropro;
  544. t = ((bt848->gpiodata[0] >> 10) - 1) & 7;
  545. tv->amux = miroamux;
  546. }
  547. else {
  548. tv->board = Bt848_miro;
  549. tv->amux = miroamux;
  550. t = ((bt848->gpiodata[0] >> 10) - 1) & 7;
  551. }
  552. if (t >= nelem(tuners))
  553. t = 4;
  554. tv->tuner = &tuners[t];
  555. tv->i2ctuneraddr =
  556. i2cread(tv, 0xc1, &v)? 0xc0:
  557. i2cread(tv, 0xc3, &v)? 0xc2:
  558. i2cread(tv, 0xc5, &v)? 0xc4:
  559. i2cread(tv, 0xc7, &v)? 0xc6: -1;
  560. bt848->capctl = capctl_fullframe;
  561. bt848->adelay = adelay_ntsc;
  562. bt848->bdelay = bdelay_ntsc;
  563. bt848->iform = iform_muxsel0|iform_xtauto|iform_ntsc;
  564. bt848->vbipacksize = vbipacksize & 0xff;
  565. bt848->vbipackdel = (vbipacksize >> 8) & 1;
  566. // setpll(bt848);
  567. tv->cfmt = bt848->colorfmt = colorfmt_rgb16;
  568. hscale = (ntsc_rawpixels * 4096) / ntsc_sqpixels - 4096;
  569. hdelay = (ntsc_clkx1delay * ntsc_hactive) / ntsc_clkx1hactive;
  570. bt848->ovtc = bt848->evtc = 0;
  571. bt848->ehscalehi = bt848->ohscalehi = (hscale >> 8) & 0xff;
  572. bt848->ehscalelo = bt848->ohscalelo = hscale & 0xff;
  573. bt848->evscalehi &= ~0x1f;
  574. bt848->ovscalehi &= ~0x1f;
  575. bt848->evscalehi |= vscale_interlaced | ((ntsc_vscale >> 8) & 0x1f);
  576. bt848->ovscalehi |= vscale_interlaced | (ntsc_vscale >> 8) & 0x1f;
  577. bt848->evscalelo = bt848->ovscalelo = ntsc_vscale & 0xff;
  578. bt848->ehactivelo = bt848->ohactivelo = ntsc_hactive & 0xff;
  579. bt848->ehdelaylo = bt848->ohdelaylo = hdelay & 0xff;
  580. bt848->evactivelo = bt848->ovactivelo = ntsc_vactive & 0xff;
  581. bt848->evdelaylo = bt848->ovdelaylo = ntsc_vdelay & 0xff;
  582. bt848->ecrop = bt848->ocrop =
  583. ((ntsc_hactive >> 8) & 0x03) |
  584. ((hdelay >> 6) & 0x0C) |
  585. ((ntsc_vactive >> 4) & 0x30) |
  586. ((ntsc_vdelay >> 2) & 0xC0);
  587. bt848->colorctl = colorctl_gamma;
  588. bt848->capctl = 0;
  589. bt848->gpiodmactl = gpiodmactl_pltp23_16 |
  590. gpiodmactl_pltp1_16 | gpiodmactl_pktp_32;
  591. bt848->gpioreginp = 0;
  592. bt848->contrastlo = contrast_100percent;
  593. bt848->bright = 16;
  594. bt848->adc = (2 << 6) | adc_crush;
  595. bt848->econtrol = bt848->ocontrol = control_ldec;
  596. bt848->escloop = bt848->oscloop = 0;
  597. bt848->intstat = (ulong)-1;
  598. bt848->intmask = intmask |
  599. intstat_vsync | intstat_scerr | intstat_risci | intstat_ocerr |
  600. intstat_vpress | intstat_fmtchg;
  601. if (tv->amux) {
  602. gpioenable(tv, ~0xfff, 0xfff);
  603. gpiowrite(tv, ~0xfff, tv->amux[AudioRadio]);
  604. }
  605. print("#V%ld: %s (rev %d) (%s/%s) intl %d\n",
  606. tv - tvs, tv->variant->name, pci->rid, boards[tv->board],
  607. tv->tuner->name, pci->intl);
  608. intrenable(pci->intl, (void (*)(Ureg *, void *))tvinterrupt,
  609. tv, pci->tbdf, "tv");
  610. }
  611. }
  612. static Chan*
  613. tvattach(char *spec)
  614. {
  615. return devattach('V', spec);
  616. }
  617. #define TYPE(q) ((int)((q).path & 0xff))
  618. #define DEV(q) ((int)(((q).path >> 8) & 0xff))
  619. #define QID(d, t) ((((d) & 0xff) << 8) | (t))
  620. static int
  621. tv1gen(Chan *c, int i, Dir *dp)
  622. {
  623. Qid qid;
  624. switch (i) {
  625. case Qvdata:
  626. mkqid(&qid, QID(DEV(c->qid), Qvdata), 0, QTFILE);
  627. devdir(c, qid, "video", 0, eve, 0444, dp);
  628. return 1;
  629. case Qadata:
  630. mkqid(&qid, QID(DEV(c->qid), Qadata), 0, QTFILE);
  631. devdir(c, qid, "audio", 0, eve, 0444, dp);
  632. return 1;
  633. case Qctl:
  634. mkqid(&qid, QID(DEV(c->qid), Qctl), 0, QTFILE);
  635. devdir(c, qid, "ctl", 0, eve, 0444, dp);
  636. return 1;
  637. case Qregs:
  638. mkqid(&qid, QID(DEV(c->qid), Qregs), 0, QTFILE);
  639. devdir(c, qid, "regs", 0, eve, 0444, dp);
  640. return 1;
  641. }
  642. return -1;
  643. }
  644. static int
  645. tvgen(Chan *c, char *, Dirtab *, int, int i, Dir *dp)
  646. {
  647. Qid qid;
  648. int dev;
  649. dev = DEV(c->qid);
  650. switch (TYPE(c->qid)) {
  651. case Qdir:
  652. if (i == DEVDOTDOT) {
  653. mkqid(&qid, Qdir, 0, QTDIR);
  654. devdir(c, qid, "#V", 0, eve, 0555, dp);
  655. return 1;
  656. }
  657. if (i >= ntvs)
  658. return -1;
  659. mkqid(&qid, QID(i, Qsubdir), 0, QTDIR);
  660. snprint(up->genbuf, sizeof(up->genbuf), "tv%d", i);
  661. devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
  662. return 1;
  663. case Qsubdir:
  664. if (i == DEVDOTDOT) {
  665. mkqid(&qid, QID(dev, Qdir), 0, QTDIR);
  666. snprint(up->genbuf, sizeof(up->genbuf), "tv%d", dev);
  667. devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
  668. return 1;
  669. }
  670. return tv1gen(c, i + Qsubbase, dp);
  671. case Qvdata:
  672. case Qadata:
  673. case Qctl:
  674. case Qregs:
  675. return tv1gen(c, TYPE(c->qid), dp);
  676. default:
  677. return -1;
  678. }
  679. }
  680. static Walkqid *
  681. tvwalk(Chan *c, Chan *nc, char **name, int nname)
  682. {
  683. return devwalk(c, nc, name, nname, 0, 0, tvgen);
  684. }
  685. static int
  686. tvstat(Chan *c, uchar *db, int n)
  687. {
  688. return devstat(c, db, n, 0, 0, tvgen);
  689. }
  690. static Chan*
  691. tvopen(Chan *c, int omode)
  692. {
  693. if (omode != OREAD &&
  694. TYPE(c->qid) != Qctl && TYPE(c->qid) != Qvdata)
  695. error(Eperm);
  696. switch (TYPE(c->qid)) {
  697. case Qdir:
  698. return devopen(c, omode, nil, 0, tvgen);
  699. case Qadata:
  700. if (tvs[DEV(c->qid)].bt878 == nil)
  701. error(Enonexist);
  702. break;
  703. }
  704. c->mode = openmode(omode);
  705. c->flag |= COPEN;
  706. c->offset = 0;
  707. if (TYPE(c->qid) == Qadata)
  708. c->aux = nil;
  709. return c;
  710. }
  711. static void
  712. tvclose(Chan *)
  713. {}
  714. static int
  715. audioblock(void *)
  716. {
  717. return 1;
  718. }
  719. static long
  720. tvread(Chan *c, void *a, long n, vlong offset)
  721. {
  722. static char regs[10 * K];
  723. static int regslen;
  724. Tv *tv;
  725. char *e, *p;
  726. uchar *src;
  727. USED(offset);
  728. switch(TYPE(c->qid)) {
  729. case Qdir:
  730. case Qsubdir:
  731. return devdirread(c, a, n, 0, 0, tvgen);
  732. case Qvdata: {
  733. int bpf, nb;
  734. tv = &tvs[DEV(c->qid)];
  735. bpf = ntsc_hactive * ntsc_vactive * getbitspp(tv) / 8;
  736. if (offset >= bpf)
  737. return 0;
  738. nb = n;
  739. if (offset + nb > bpf)
  740. nb = bpf - offset;
  741. ilock(tv);
  742. if (tv->frames == nil || tv->lvframe >= tv->nframes ||
  743. tv->frames[tv->lvframe].fbase == nil) {
  744. iunlock(tv);
  745. return 0;
  746. }
  747. src = tv->frames[tv->lvframe].fbase;
  748. incref(&tv->fref);
  749. iunlock(tv);
  750. memmove(a, src + offset, nb);
  751. decref(&tv->fref);
  752. return nb;
  753. }
  754. case Qadata: {
  755. ulong uablock = (ulong)c->aux, bnum, tvablock;
  756. int boffs, nbytes;
  757. tv = &tvs[DEV(c->qid)];
  758. if (tv->bt878 == nil)
  759. error("#V: No audio device");
  760. if (tv->absize == 0)
  761. error("#V: audio not initialized");
  762. bnum = offset / tv->absize;
  763. boffs = offset % tv->absize;
  764. nbytes = tv->absize - boffs;
  765. incref(&tv->aref);
  766. while (1) {
  767. tvablock = tv->narblocks; // Current tv block.
  768. if (uablock == 0)
  769. uablock = tvablock - 1;
  770. if (tvablock >= uablock + bnum + tv->narblocks)
  771. uablock = tvablock - 1 - bnum;
  772. if (uablock + bnum == tvablock) {
  773. sleep(tv, audioblock, nil);
  774. continue;
  775. }
  776. break;
  777. }
  778. print("uablock %ld, bnum %ld, boffs %d, nbytes %d, tvablock %ld\n",
  779. uablock, bnum, boffs, nbytes, tvablock);
  780. src = tv->abuf + ((uablock + bnum) % tv->nablocks) * tv->absize;
  781. print("copying from %.8ulX (abuf %.8ulX), nbytes %d (block %ld.%ld)\n",
  782. src + boffs, tv->abuf, nbytes, uablock, bnum);
  783. memmove(a, src + boffs, nbytes);
  784. decref(&tv->aref);
  785. uablock += (boffs + nbytes) % tv->absize;
  786. c->aux = (void*)uablock;
  787. return nbytes;
  788. }
  789. case Qctl: {
  790. char str[128];
  791. tv = &tvs[DEV(c->qid)];
  792. snprint(str, sizeof str, "%dx%dx%d %s channel %d %s\n",
  793. ntsc_hactive, ntsc_vactive, getbitspp(tv),
  794. getcolormode(tv->cfmt), tv->channel,
  795. tv->ainfo);
  796. return readstr(offset, a, strlen(str) + 1, str);
  797. }
  798. case Qregs:
  799. if (offset == 0) {
  800. Bt848 *bt848;
  801. int i;
  802. tv = &tvs[DEV(c->qid)];
  803. bt848 = tv->bt848;
  804. e = regs + sizeof(regs);
  805. p = regs;
  806. for (i = 0; i < 0x300 >> 2; i++)
  807. p = seprint(p, e, "%.3X %.8ulX\n", i << 2, ((ulong *)bt848)[i]);
  808. if (tv->bt878) {
  809. bt848 = tv->bt878;
  810. for (i = 0; i < 0x300 >> 2; i++)
  811. p = seprint(p, e, "%.3X %.8ulX\n",
  812. i << 2, ((ulong *)bt848)[i]);
  813. }
  814. regslen = p - regs;
  815. }
  816. if (offset >= regslen)
  817. return 0;
  818. if (offset + n > regslen)
  819. n = regslen - offset;
  820. return readstr(offset, a, n, &regs[offset]);
  821. default:
  822. n = 0;
  823. break;
  824. }
  825. return n;
  826. }
  827. static long
  828. tvwrite(Chan *c, void *a, long n, vlong)
  829. {
  830. Cmdbuf *cb;
  831. Cmdtab *ct;
  832. Tv *tv;
  833. tv = &tvs[DEV(c->qid)];
  834. switch(TYPE(c->qid)) {
  835. case Qctl:
  836. cb = parsecmd(a, n);
  837. if(waserror()){
  838. free(cb);
  839. nexterror();
  840. }
  841. ct = lookupcmd(cb, tvctlmsg, nelem(tvctlmsg));
  842. switch (ct->index) {
  843. case CMvstart:
  844. vstart(tv, (int)strtol(cb->f[1], (char **)nil, 0),
  845. ntsc_hactive, ntsc_vactive, ntsc_hactive);
  846. break;
  847. case CMastart:
  848. astart(tv, cb->f[1], (uint)strtol(cb->f[2], (char **)nil, 0),
  849. (uint)strtol(cb->f[3], (char **)nil, 0),
  850. (uint)strtol(cb->f[4], (char **)nil, 0));
  851. break;
  852. case CMastop:
  853. astop(tv);
  854. break;
  855. case CMvgastart:
  856. vgastart(tv, strtoul(cb->f[1], (char **)nil, 0),
  857. (int)strtoul(cb->f[2], (char **)nil, 0));
  858. break;
  859. case CMvstop:
  860. vstop(tv);
  861. break;
  862. case CMchannel:
  863. frequency(tv, (int)strtol(cb->f[1], (char **)nil, 0),
  864. (int)strtol(cb->f[2], (char **)nil, 0));
  865. break;
  866. case CMcolormode:
  867. colormode(tv, cb->f[1]);
  868. break;
  869. case CMvolume:
  870. if (!tv->msp)
  871. error("#V: No volume control");
  872. mspvolume(tv, 0, (int)strtol(cb->f[1], (char **)nil, 0),
  873. (int)strtol(cb->f[2], (char **)nil, 0));
  874. break;
  875. case CMmute:
  876. if (!tv->msp)
  877. error("#V: No volume control");
  878. mspvolume(tv, 1, 0, 0);
  879. break;
  880. }
  881. poperror();
  882. free(cb);
  883. break;
  884. default:
  885. error(Eio);
  886. }
  887. return n;
  888. }
  889. Dev tvdevtab = {
  890. 'V',
  891. "tv",
  892. devreset,
  893. tvinit,
  894. devshutdown,
  895. tvattach,
  896. tvwalk,
  897. tvstat,
  898. tvopen,
  899. devcreate,
  900. tvclose,
  901. tvread,
  902. devbread,
  903. tvwrite,
  904. devbwrite,
  905. devremove,
  906. devwstat,
  907. };
  908. static void
  909. tvinterrupt(Ureg *, Tv *tv)
  910. {
  911. Bt848 *bt848 = tv->bt848,
  912. *bt878 = tv->bt878;
  913. while (1) {
  914. ulong vstat, astat;
  915. uchar fnum;
  916. vstat = bt848->intstat;
  917. fnum = (vstat >> intstat_riscstatshift) & 0xf;
  918. vstat &= bt848->intmask;
  919. if (bt878)
  920. astat = bt878->intstat & bt878->intmask;
  921. else
  922. astat = 0;
  923. if (vstat == 0 && astat == 0)
  924. break;
  925. if (astat)
  926. print("vstat %.8luX, astat %.8luX\n", vstat, astat);
  927. bt848->intstat = vstat;
  928. if (bt878)
  929. bt878->intstat = astat;
  930. if ((vstat & intstat_fmtchg) == intstat_fmtchg) {
  931. iprint("int: fmtchg\n");
  932. vstat &= ~intstat_fmtchg;
  933. }
  934. if ((vstat & intstat_vpress) == intstat_vpress) {
  935. // iprint("int: vpress\n");
  936. vstat &= ~intstat_vpress;
  937. }
  938. if ((vstat & intstat_vsync) == intstat_vsync) {
  939. vstat &= ~intstat_vsync;
  940. }
  941. if ((vstat & intstat_scerr) == intstat_scerr) {
  942. iprint("int: scerr\n");
  943. bt848->gpiodmactl &=
  944. ~(gpiodmactl_riscenable|gpiodmactl_fifoenable);
  945. bt848->gpiodmactl |= gpiodmactl_fifoenable;
  946. bt848->gpiodmactl |= gpiodmactl_riscenable;
  947. vstat &= ~intstat_scerr;
  948. }
  949. if ((vstat & intstat_risci) == intstat_risci) {
  950. tv->lvframe = fnum;
  951. vstat &= ~intstat_risci;
  952. }
  953. if ((vstat & intstat_ocerr) == intstat_ocerr) {
  954. iprint("int: ocerr\n");
  955. vstat &= ~intstat_ocerr;
  956. }
  957. if ((vstat & intstat_fbus) == intstat_fbus) {
  958. iprint("int: fbus\n");
  959. vstat &= ~intstat_fbus;
  960. }
  961. if (vstat)
  962. iprint("int: (v) ignored interrupts %.8ulX\n", vstat);
  963. if ((astat & intstat_risci) == intstat_risci) {
  964. tv->narblocks++;
  965. if ((tv->narblocks % 100) == 0)
  966. print("a");
  967. wakeup(tv);
  968. astat &= ~intstat_risci;
  969. }
  970. if ((astat & intstat_fdsr) == intstat_fdsr) {
  971. iprint("int: (a) fdsr\n");
  972. bt848->gpiodmactl &=
  973. ~(gpiodmactl_acapenable |
  974. gpiodmactl_riscenable | gpiodmactl_fifoenable);
  975. astat &= ~intstat_fdsr;
  976. }
  977. if (astat)
  978. iprint("int: (a) ignored interrupts %.8ulX\n", astat);
  979. }
  980. }
  981. static int
  982. i2cread(Tv *tv, uchar off, uchar *v)
  983. {
  984. Bt848 *bt848 = tv->bt848;
  985. ulong intstat;
  986. int i;
  987. bt848->intstat = intstat_i2cdone;
  988. bt848->i2c = (off << 24) | tv->i2ccmd;
  989. intstat = -1;
  990. for (i = 0; i != 1000; i++) {
  991. if ((intstat = bt848->intstat) & intstat_i2cdone)
  992. break;
  993. microdelay(1000);
  994. }
  995. if (i == 1000) {
  996. print("i2cread: timeout\n");
  997. return 0;
  998. }
  999. if ((intstat & intstat_i2crack) == 0)
  1000. return 0;
  1001. *v = bt848->i2c >> 8;
  1002. return 1;
  1003. }
  1004. static int
  1005. i2cwrite(Tv *tv, uchar addr, uchar sub, uchar data, int both)
  1006. {
  1007. Bt848 *bt848 = tv->bt848;
  1008. ulong intstat, d;
  1009. int i;
  1010. bt848->intstat = intstat_i2cdone;
  1011. d = (addr << 24) | (sub << 16) | tv->i2ccmd;
  1012. if (both)
  1013. d |= (data << 8) | i2c_bt848w3b;
  1014. bt848->i2c = d;
  1015. intstat = 0;
  1016. for (i = 0; i != 1000; i++) {
  1017. if ((intstat = bt848->intstat) & intstat_i2cdone)
  1018. break;
  1019. microdelay(1000);
  1020. }
  1021. if (i == i2c_timeout) {
  1022. print("i2cwrite: timeout\n");
  1023. return 0;
  1024. }
  1025. if ((intstat & intstat_i2crack) == 0)
  1026. return 0;
  1027. return 1;
  1028. }
  1029. static ulong *
  1030. riscpacked(ulong pa, int fnum, int w, int h, int stride, ulong **lastjmp)
  1031. {
  1032. ulong *p, *pbase;
  1033. int i;
  1034. pbase = p = (ulong *)malloc((h + 6) * 2 * sizeof(ulong));
  1035. assert(p);
  1036. assert(w <= 0x7FF);
  1037. *p++ = riscsync | riscsync_resync | riscsync_vre;
  1038. *p++ = 0;
  1039. *p++ = riscsync | riscsync_fm1;
  1040. *p++ = 0;
  1041. for (i = 0; i != h / 2; i++) {
  1042. *p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
  1043. *p++ = pa + i * 2 * stride;
  1044. }
  1045. *p++ = riscsync | riscsync_resync | riscsync_vro;
  1046. *p++ = 0;
  1047. *p++ = riscsync | riscsync_fm1;
  1048. *p++ = 0;
  1049. for (i = 0; i != h / 2; i++) {
  1050. *p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;
  1051. *p++ = pa + (i * 2 + 1) * stride;
  1052. }
  1053. // reset status. you really need two instructions ;-(.
  1054. *p++ = riscjmp | (0xf << risclabelshift_reset);
  1055. *p++ = PADDR(p);
  1056. *p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
  1057. *lastjmp = p;
  1058. return pbase;
  1059. }
  1060. static ulong *
  1061. riscplanar411(ulong pa, int fnum, int w, int h, ulong **lastjmp)
  1062. {
  1063. ulong *p, *pbase, Cw, Yw, Ch;
  1064. uchar *Ybase, *Cbbase, *Crbase;
  1065. int i, bitspp;
  1066. bitspp = 6;
  1067. assert(w * bitspp / 8 <= 0x7FF);
  1068. pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
  1069. assert(p);
  1070. Yw = w;
  1071. Ybase = (uchar *)pa;
  1072. Cw = w >> 1;
  1073. Ch = h >> 1;
  1074. Cbbase = Ybase + Yw * h;
  1075. Crbase = Cbbase + Cw * Ch;
  1076. *p++ = riscsync | riscsync_resync | riscsync_vre;
  1077. *p++ = 0;
  1078. *p++ = riscsync | riscsync_fm3;
  1079. *p++ = 0;
  1080. for (i = 0; i != h / 2; i++) {
  1081. *p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
  1082. *p++ = (Cw << 16) | Cw;
  1083. *p++ = (ulong)(Ybase + i * 2 * Yw);
  1084. *p++ = (ulong)(Cbbase + i * Cw); // Do not interlace
  1085. *p++ = (ulong)(Crbase + i * Cw);
  1086. }
  1087. *p++ = riscsync | riscsync_resync | riscsync_vro;
  1088. *p++ = 0;
  1089. *p++ = riscsync | riscsync_fm3;
  1090. *p++ = 0;
  1091. for (i = 0; i != h / 2; i++) {
  1092. *p++ = riscwrite1s23 | Yw | riscwrite_sol | riscwrite_eol;
  1093. *p++ = (Cw << 16) | Cw;
  1094. *p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
  1095. }
  1096. // reset status. you really need two instructions ;-(.
  1097. *p++ = riscjmp | (0xf << risclabelshift_reset);
  1098. *p++ = PADDR(p);
  1099. *p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
  1100. *lastjmp = p;
  1101. return pbase;
  1102. }
  1103. static ulong *
  1104. riscplanar422(ulong pa, int fnum, int w, int h, ulong **lastjmp)
  1105. {
  1106. ulong *p, *pbase, Cw, Yw;
  1107. uchar *Ybase, *Cbbase, *Crbase;
  1108. int i, bpp;
  1109. bpp = 2;
  1110. assert(w * bpp <= 0x7FF);
  1111. pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));
  1112. assert(p);
  1113. Yw = w;
  1114. Ybase = (uchar *)pa;
  1115. Cw = w >> 1;
  1116. Cbbase = Ybase + Yw * h;
  1117. Crbase = Cbbase + Cw * h;
  1118. *p++ = riscsync | riscsync_resync | riscsync_vre;
  1119. *p++ = 0;
  1120. *p++ = riscsync | riscsync_fm3;
  1121. *p++ = 0;
  1122. for (i = 0; i != h / 2; i++) {
  1123. *p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
  1124. *p++ = (Cw << 16) | Cw;
  1125. *p++ = (ulong)(Ybase + i * 2 * Yw);
  1126. *p++ = (ulong)(Cbbase + i * 2 * Cw);
  1127. *p++ = (ulong)(Crbase + i * 2 * Cw);
  1128. }
  1129. *p++ = riscsync | riscsync_resync | riscsync_vro;
  1130. *p++ = 0;
  1131. *p++ = riscsync | riscsync_fm3;
  1132. *p++ = 0;
  1133. for (i = 0; i != h / 2; i++) {
  1134. *p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;
  1135. *p++ = (Cw << 16) | Cw;
  1136. *p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);
  1137. *p++ = (ulong)(Cbbase + (i * 2 + 1) * Cw);
  1138. *p++ = (ulong)(Crbase + (i * 2 + 1) * Cw);
  1139. }
  1140. // reset status. you really need two instructions ;-(.
  1141. *p++ = riscjmp | (0xf << risclabelshift_reset);
  1142. *p++ = PADDR(p);
  1143. *p++ = riscjmp | riscirq | (fnum << risclabelshift_set);
  1144. *lastjmp = p;
  1145. return pbase;
  1146. }
  1147. static ulong *
  1148. riscaudio(ulong pa, int nblocks, int bsize)
  1149. {
  1150. ulong *p, *pbase;
  1151. int i;
  1152. pbase = p = (ulong *)malloc((nblocks + 3) * 2 * sizeof(ulong));
  1153. assert(p);
  1154. *p++ = riscsync|riscsync_fm1;
  1155. *p++ = 0;
  1156. for (i = 0; i != nblocks; i++) {
  1157. *p++ = riscwrite | riscwrite_sol | riscwrite_eol | bsize | riscirq |
  1158. ((i & 0xf) << risclabelshift_set) |
  1159. ((~i & 0xf) << risclabelshift_reset);
  1160. *p++ = pa + i * bsize;
  1161. }
  1162. *p++ = riscsync | riscsync_vro;
  1163. *p++ = 0;
  1164. *p++ = riscjmp;
  1165. *p++ = PADDR(pbase);
  1166. USED(p);
  1167. return pbase;
  1168. }
  1169. static void
  1170. vactivate(Tv *tv, Frame *frames, int nframes)
  1171. {
  1172. Bt848 *bt848 = tv->bt848;
  1173. ilock(tv);
  1174. if (tv->frames) {
  1175. iunlock(tv);
  1176. error(Einuse);
  1177. }
  1178. poperror();
  1179. tv->frames = frames;
  1180. tv->nframes = nframes;
  1181. bt848->riscstrtadd = PADDR(tv->frames[0].fstart);
  1182. bt848->capctl |= capctl_captureodd|capctl_captureeven;
  1183. bt848->gpiodmactl |= gpiodmactl_fifoenable;
  1184. bt848->gpiodmactl |= gpiodmactl_riscenable;
  1185. iunlock(tv);
  1186. }
  1187. static void
  1188. vstart(Tv *tv, int nframes, int w, int h, int stride)
  1189. {
  1190. Frame *frames;
  1191. int bitspp, i, bpf;
  1192. if (nframes >= 0x10)
  1193. error(Ebadarg);
  1194. bitspp = getbitspp(tv);
  1195. bpf = w * h * bitspp / 8;
  1196. // Add one as a spare.
  1197. frames = (Frame *)malloc(nframes * sizeof(Frame));
  1198. assert(frames);
  1199. if (waserror()) {
  1200. for (i = 0; i != nframes; i++)
  1201. if (frames[i].fbase)
  1202. free(frames[i].fbase);
  1203. free(frames);
  1204. nexterror();
  1205. }
  1206. memset(frames, 0, nframes * sizeof(Frame));
  1207. for (i = 0; i != nframes; i++) {
  1208. if ((frames[i].fbase = (uchar *)malloc(bpf)) == nil)
  1209. error(Enomem);
  1210. switch (tv->cfmt) {
  1211. case colorfmt_YCbCr422:
  1212. frames[i].fstart = riscplanar422(PADDR(frames[i].fbase), i,
  1213. w, h, &frames[i].fjmp);
  1214. break;
  1215. case colorfmt_YCbCr411:
  1216. frames[i].fstart = riscplanar411(PADDR(frames[i].fbase), i,
  1217. w, h, &frames[i].fjmp);
  1218. break;
  1219. case colorfmt_rgb16:
  1220. frames[i].fstart = riscpacked(PADDR(frames[i].fbase), i,
  1221. w * bitspp / 8, h, stride * bitspp / 8,
  1222. &frames[i].fjmp);
  1223. break;
  1224. default:
  1225. panic("vstart: Unsupport colorformat\n");
  1226. }
  1227. }
  1228. for (i = 0; i != nframes; i++)
  1229. *frames[i].fjmp =
  1230. PADDR((i == nframes - 1)? frames[0].fstart: frames[i + 1].fstart);
  1231. vactivate(tv, frames, nframes);
  1232. }
  1233. static void
  1234. astart(Tv *tv, char *input, uint rate, uint nab, uint nasz)
  1235. {
  1236. Bt848 *bt878 = tv->bt878;
  1237. ulong *arisc;
  1238. int selector;
  1239. uchar *abuf;
  1240. int s, d;
  1241. if (bt878 == nil || tv->amux == nil)
  1242. error("#V: Card does not support audio");
  1243. selector = 0;
  1244. if (!strcmp(input, "tv"))
  1245. selector = asel_tv;
  1246. else if (!strcmp(input, "radio"))
  1247. selector = asel_radio;
  1248. else if (!strcmp(input, "mic"))
  1249. selector = asel_mic;
  1250. else if (!strcmp(input, "smxc"))
  1251. selector = asel_smxc;
  1252. else
  1253. error("#V: Invalid input");
  1254. if (nasz > 0xfff)
  1255. error("#V: Audio block size too big (max 0xfff)");
  1256. abuf = (uchar *)malloc(nab * nasz * sizeof(uchar));
  1257. assert(abuf);
  1258. arisc = riscaudio(PADDR(abuf), nab, nasz);
  1259. ilock(tv);
  1260. if (tv->arisc) {
  1261. iunlock(tv);
  1262. free(abuf);
  1263. free(arisc);
  1264. error(Einuse);
  1265. }
  1266. tv->arisc = arisc;
  1267. tv->abuf = abuf;
  1268. tv->nablocks = nab;
  1269. tv->absize = nasz;
  1270. bt878->riscstrtadd = PADDR(tv->arisc);
  1271. bt878->packetlen = (nab << 16) | nasz;
  1272. bt878->intmask =
  1273. intstat_scerr | intstat_ocerr | intstat_risci |
  1274. intstat_pabort | intstat_riperr | intstat_pperr |
  1275. intstat_fdsr | intstat_ftrgt | intstat_fbus;
  1276. /* Assume analog, 16bpp */
  1277. for (s = 0; s < 16; s++)
  1278. if (rate << s > Hwbase_ad * 4 / 15)
  1279. break;
  1280. for (d = 15; d >= 4; d--)
  1281. if (rate << s < Hwbase_ad * 4 / d)
  1282. break;
  1283. print("astart: sampleshift %d, decimation %d\n", s, d);
  1284. tv->narblocks = 0;
  1285. bt878->gpiodmactl = gpiodmactl_fifoenable |
  1286. gpiodmactl_riscenable | gpiodmactl_acapenable |
  1287. gpiodmactl_daes2 | /* gpiodmactl_apwrdn | */
  1288. gpiodmactl_daiomda | (d << 8) | (9 << 28) | (selector << 24);
  1289. print("dmactl %.8ulX\n", bt878->gpiodmactl);
  1290. iunlock(tv);
  1291. }
  1292. static void
  1293. astop(Tv *tv)
  1294. {
  1295. Bt848 *bt878 = tv->bt878;
  1296. ilock(tv);
  1297. if (tv->aref.ref > 0) {
  1298. iunlock(tv);
  1299. error(Einuse);
  1300. }
  1301. if (tv->abuf) {
  1302. bt878->gpiodmactl &= ~gpiodmactl_riscenable;
  1303. bt878->gpiodmactl &= ~gpiodmactl_fifoenable;
  1304. free(tv->abuf);
  1305. tv->abuf = nil;
  1306. free(tv->arisc);
  1307. tv->arisc = nil;
  1308. }
  1309. iunlock(tv);
  1310. }
  1311. static void
  1312. vgastart(Tv *tv, ulong pa, int stride)
  1313. {
  1314. Frame *frame;
  1315. frame = (Frame *)malloc(sizeof(Frame));
  1316. assert(frame);
  1317. if (waserror()) {
  1318. free(frame);
  1319. nexterror();
  1320. }
  1321. frame->fbase = nil;
  1322. frame->fstart = riscpacked(pa, 0, ntsc_hactive * getbitspp(tv) / 8,
  1323. ntsc_vactive, stride * getbitspp(tv) / 8,
  1324. &frame->fjmp);
  1325. *frame->fjmp = PADDR(frame->fstart);
  1326. vactivate(tv, frame, 1);
  1327. }
  1328. static void
  1329. vstop(Tv *tv)
  1330. {
  1331. Bt848 *bt848 = tv->bt848;
  1332. ilock(tv);
  1333. if (tv->fref.ref > 0) {
  1334. iunlock(tv);
  1335. error(Einuse);
  1336. }
  1337. if (tv->frames) {
  1338. int i;
  1339. bt848->gpiodmactl &= ~gpiodmactl_riscenable;
  1340. bt848->gpiodmactl &= ~gpiodmactl_fifoenable;
  1341. bt848->capctl &= ~(capctl_captureodd|capctl_captureeven);
  1342. for (i = 0; i != tv->nframes; i++)
  1343. if (tv->frames[i].fbase)
  1344. free(tv->frames[i].fbase);
  1345. free(tv->frames);
  1346. tv->frames = nil;
  1347. }
  1348. iunlock(tv);
  1349. }
  1350. static long
  1351. hrcfreq[] = { /* HRC CATV frequencies */
  1352. 0, 7200, 5400, 6000, 6600, 7800, 8400, 17400,
  1353. 18000, 18600, 19200, 19800, 20400, 21000, 12000, 12600,
  1354. 13200, 13800, 14400, 15000, 15600, 16200, 16800, 21600,
  1355. 22200, 22800, 23400, 24000, 24600, 25200, 25800, 26400,
  1356. 27000, 27600, 28200, 28800, 29400, 30000, 30600, 31200,
  1357. 31800, 32400, 33000, 33600, 34200, 34800, 35400, 36000,
  1358. 36600, 37200, 37800, 38400, 39000, 39600, 40200, 40800,
  1359. 41400, 42000, 42600, 43200, 43800, 44400, 45000, 45600,
  1360. 46200, 46800, 47400, 48000, 48600, 49200, 49800, 50400,
  1361. 51000, 51600, 52200, 52800, 53400, 54000, 54600, 55200,
  1362. 55800, 56400, 57000, 57600, 58200, 58800, 59400, 60000,
  1363. 60600, 61200, 61800, 62400, 63000, 63600, 64200, 9000,
  1364. 9600, 10200, 10800, 11400, 64800, 65400, 66000, 66600,
  1365. 67200, 67800, 68400, 69000, 69600, 70200, 70800, 71400,
  1366. 72000, 72600, 73200, 73800, 74400, 75000, 75600, 76200,
  1367. 76800, 77400, 78000, 78600, 79200, 79800,
  1368. };
  1369. static void
  1370. frequency(Tv *tv, int channel, int finetune)
  1371. {
  1372. Tuner *tuner = tv->tuner;
  1373. long freq;
  1374. ushort div;
  1375. uchar cfg;
  1376. if (channel < 0 || channel > nelem(hrcfreq))
  1377. error(Ebadarg);
  1378. freq = (hrcfreq[channel] * Freqmultiplier) / 100;
  1379. if (freq < tuner->freq_vhfh)
  1380. cfg = tuner->VHF_L;
  1381. else if (freq < tuner->freq_uhf)
  1382. cfg = tuner->VHF_H;
  1383. else
  1384. cfg = tuner->UHF;
  1385. div = (freq + tuner->offs + finetune) & 0x7fff;
  1386. if (!i2cwrite(tv, tv->i2ctuneraddr, (div >> 8) & 0x7f, div, 1))
  1387. error(Eio);
  1388. if (!i2cwrite(tv, tv->i2ctuneraddr, tuner->cfg, cfg, 1))
  1389. error(Eio);
  1390. tv->channel = channel;
  1391. if (tv->msp)
  1392. msptune(tv);
  1393. }
  1394. static struct {
  1395. char *cmode;
  1396. ulong realmode;
  1397. ulong cbits;
  1398. } colormodes[] = {
  1399. { "RGB16", colorfmt_rgb16, colorfmt_rgb16, },
  1400. { "YCbCr422", colorfmt_YCbCr422, colorfmt_YCbCr422, },
  1401. { "YCbCr411", colorfmt_YCbCr411, colorfmt_YCbCr422, },
  1402. };
  1403. static void
  1404. colormode(Tv *tv, char *colormode)
  1405. {
  1406. Bt848 *bt848 = tv->bt848;
  1407. int i;
  1408. for (i = 0; i != nelem(colormodes); i++)
  1409. if (!strcmp(colormodes[i].cmode, colormode))
  1410. break;
  1411. if (i == nelem(colormodes))
  1412. error(Ebadarg);
  1413. tv->cfmt = colormodes[i].realmode;
  1414. bt848->colorfmt = colormodes[i].cbits;
  1415. }
  1416. static int
  1417. getbitspp(Tv *tv)
  1418. {
  1419. switch (tv->cfmt) {
  1420. case colorfmt_rgb16:
  1421. case colorfmt_YCbCr422:
  1422. return 16;
  1423. case colorfmt_YCbCr411:
  1424. return 12;
  1425. default:
  1426. error("getbitspp: Unsupport color format\n");
  1427. }
  1428. return -1;
  1429. }
  1430. static char *
  1431. getcolormode(ulong cmode)
  1432. {
  1433. switch (cmode) {
  1434. case colorfmt_rgb16:
  1435. return "RGB16";
  1436. case colorfmt_YCbCr411:
  1437. return "YCbCr411";
  1438. case colorfmt_YCbCr422:
  1439. return (cmode == colorfmt_YCbCr422)? "YCbCr422": "YCbCr411";
  1440. default:
  1441. error("getcolormode: Unsupport color format\n");
  1442. }
  1443. return nil;
  1444. }
  1445. static void
  1446. i2c_set(Tv *tv, int scl, int sda)
  1447. {
  1448. Bt848 *bt848 = tv->bt848;
  1449. ulong d;
  1450. bt848->i2c = (scl << 1) | sda;
  1451. d = bt848->i2c;
  1452. USED(d);
  1453. microdelay(i2c_delay);
  1454. }
  1455. static uchar
  1456. i2c_getsda(Tv *tv)
  1457. {
  1458. Bt848 *bt848 = tv->bt848;
  1459. return bt848->i2c & i2c_sda;
  1460. }
  1461. static void
  1462. i2c_start(Tv *tv)
  1463. {
  1464. i2c_set(tv, 0, 1);
  1465. i2c_set(tv, 1, 1);
  1466. i2c_set(tv, 1, 0);
  1467. i2c_set(tv, 0, 0);
  1468. }
  1469. static void
  1470. i2c_stop(Tv *tv)
  1471. {
  1472. i2c_set(tv, 0, 0);
  1473. i2c_set(tv, 1, 0);
  1474. i2c_set(tv, 1, 1);
  1475. }
  1476. static void
  1477. i2c_bit(Tv *tv, int sda)
  1478. {
  1479. i2c_set(tv, 0, sda);
  1480. i2c_set(tv, 1, sda);
  1481. i2c_set(tv, 0, sda);
  1482. }
  1483. static int
  1484. i2c_getack(Tv *tv)
  1485. {
  1486. int ack;
  1487. i2c_set(tv, 0, 1);
  1488. i2c_set(tv, 1, 1);
  1489. ack = i2c_getsda(tv);
  1490. i2c_set(tv, 0, 1);
  1491. return ack;
  1492. }
  1493. static int
  1494. i2c_wr8(Tv *tv, uchar d, int wait)
  1495. {
  1496. int i, ack;
  1497. i2c_set(tv, 0, 0);
  1498. for (i = 0; i != 8; i++) {
  1499. i2c_bit(tv, (d & 0x80)? 1: 0);
  1500. d <<= 1;
  1501. }
  1502. if (wait)
  1503. microdelay(wait);
  1504. ack = i2c_getack(tv);
  1505. return ack == 0;
  1506. }
  1507. static uchar
  1508. i2c_rd8(Tv *tv, int lastbyte)
  1509. {
  1510. int i;
  1511. uchar d;
  1512. d = 0;
  1513. i2c_set(tv, 0, 1);
  1514. for (i = 0; i != 8; i++) {
  1515. i2c_set(tv, 1, 1);
  1516. d <<= 1;
  1517. if (i2c_getsda(tv))
  1518. d |= 1;
  1519. i2c_set(tv, 0, 1);
  1520. }
  1521. i2c_bit(tv, lastbyte? 1: 0);
  1522. return d;
  1523. }
  1524. static int
  1525. mspsend(Tv *tv, uchar *cmd, int ncmd)
  1526. {
  1527. int i, j, delay;
  1528. for (i = 0; i != 3; i++) {
  1529. delay = 2000;
  1530. i2c_start(tv);
  1531. for (j = 0; j != ncmd; j++) {
  1532. if (!i2c_wr8(tv, cmd[j], delay))
  1533. break;
  1534. delay = 0;
  1535. }
  1536. i2c_stop(tv);
  1537. if (j == ncmd)
  1538. return 1;
  1539. microdelay(10000);
  1540. print("mspsend: retrying\n");
  1541. }
  1542. return 0;
  1543. }
  1544. static int
  1545. mspwrite(Tv *tv, uchar sub, ushort reg, ushort v)
  1546. {
  1547. uchar b[6];
  1548. b[0] = i2c_msp3400;
  1549. b[1] = sub;
  1550. b[2] = reg >> 8;
  1551. b[3] = reg;
  1552. b[4] = v >> 8;
  1553. b[5] = v;
  1554. return mspsend(tv, b, sizeof b);
  1555. }
  1556. static int
  1557. mspread(Tv *tv, uchar sub, ushort reg, ushort *data)
  1558. {
  1559. uchar b[4];
  1560. int i;
  1561. b[0] = i2c_msp3400;
  1562. b[1] = sub;
  1563. b[2] = reg >> 8;
  1564. b[3] = reg;
  1565. for (i = 0; i != 3; i++) {
  1566. i2c_start(tv);
  1567. if (!i2c_wr8(tv, b[0], 2000) ||
  1568. !i2c_wr8(tv, b[1] | 1, 0) ||
  1569. !i2c_wr8(tv, b[2], 0) ||
  1570. !i2c_wr8(tv, b[3], 0)) {
  1571. i2c_stop(tv);
  1572. microdelay(10000);
  1573. print("retrying\n");
  1574. continue;
  1575. }
  1576. i2c_start(tv);
  1577. if (!i2c_wr8(tv, b[0] | 1, 2000)) {
  1578. i2c_stop(tv);
  1579. continue;
  1580. }
  1581. *data = i2c_rd8(tv, 0) << 8;
  1582. *data |= i2c_rd8(tv, 1);
  1583. i2c_stop(tv);
  1584. return 1;
  1585. }
  1586. return 0;
  1587. }
  1588. static uchar mspt_reset[] = { i2c_msp3400, 0, 0x80, 0 };
  1589. static uchar mspt_on[] = { i2c_msp3400, 0, 0, 0 };
  1590. static int
  1591. mspreset(Tv *tv)
  1592. {
  1593. ushort v, p;
  1594. Bt848 *bt848 = tv->bt848;
  1595. ulong b;
  1596. b = 1 << 5;
  1597. gpioenable(tv, ~b, b);
  1598. gpiowrite(tv, ~b, 0);
  1599. microdelay(2500);
  1600. gpiowrite(tv, ~b, b);
  1601. bt848->i2c = 0x80;
  1602. microdelay(2000);
  1603. mspsend(tv, mspt_reset, sizeof mspt_reset);
  1604. microdelay(2000);
  1605. if (!mspsend(tv, mspt_on, sizeof mspt_on)) {
  1606. print("#V: Cannot find MSP34x5G on the I2C bus (on)\n");
  1607. return 0;
  1608. }
  1609. microdelay(2000);
  1610. if (!mspread(tv, msp_bbp, 0x001e, &v)) {
  1611. print("#V: Cannot read MSP34xG5 chip version\n");
  1612. return 0;
  1613. }
  1614. if (!mspread(tv, msp_bbp, 0x001f, &p)) {
  1615. print("#V: Cannot read MSP34xG5 product code\n");
  1616. return 0;
  1617. }
  1618. print("#V: MSP34%dg ROM %.d, %d.%d\n",
  1619. (uchar)(p >> 8), (uchar)p, (uchar)(v >> 8), (uchar)v);
  1620. tv->msp = 1;
  1621. return 1;
  1622. }
  1623. static void
  1624. mspvolume(Tv *tv, int mute, int l, int r)
  1625. {
  1626. short v, d;
  1627. ushort b;
  1628. if (mute) {
  1629. v = 0;
  1630. b = 0;
  1631. }
  1632. else {
  1633. tv->aleft = l;
  1634. tv->aright = r;
  1635. d = v = max(l, r);
  1636. if (d == 0)
  1637. d++;
  1638. b = ((r - l) * 0x7f) / d;
  1639. }
  1640. mspwrite(tv, msp_bbp, 0, v << 8);
  1641. mspwrite(tv, msp_bbp, 7, v? 0x4000: 0);
  1642. mspwrite(tv, msp_bbp, 1, b << 8);
  1643. }
  1644. static char *
  1645. mspaformat(int f)
  1646. {
  1647. switch (f) {
  1648. case 0:
  1649. return "unknown";
  1650. case 2:
  1651. case 0x20:
  1652. case 0x30:
  1653. return "M-BTSC";
  1654. case 3:
  1655. return "B/G-FM";
  1656. case 4:
  1657. case 9:
  1658. case 0xB:
  1659. return "L-AM/NICAM D/Kn";
  1660. case 8:
  1661. return "B/G-NICAM";
  1662. case 0xA:
  1663. return "I";
  1664. case 0x40:
  1665. return "FM-Radio";
  1666. }
  1667. return "unknown format";
  1668. }
  1669. static void
  1670. msptune(Tv *tv)
  1671. {
  1672. ushort d, s, nicam;
  1673. int i;
  1674. mspvolume(tv, 1, 0, 0);
  1675. if (!mspwrite(tv, msp_dem, 0x0030, 0x2033))
  1676. error("#V: Cannot set MODUS register");
  1677. if (!mspwrite(tv, msp_bbp, 0x0008, 0x0320))
  1678. error("#V: Cannot set loadspeaker input");
  1679. if (!mspwrite(tv, msp_dem, 0x0040, 0x0001))
  1680. error("#V: Cannot set I2S clock freq");
  1681. if (!mspwrite(tv, msp_bbp, 0x000d, 0x1900))
  1682. error("#V: Cannot set SCART prescale");
  1683. if (!mspwrite(tv, msp_bbp, 0x000e, 0x2403))
  1684. error("#V: Cannot set FM/AM prescale");
  1685. if (!mspwrite(tv, msp_bbp, 0x0010, 0x5a00))
  1686. error("#V: Cannot set NICAM prescale");
  1687. if (!mspwrite(tv, msp_dem, 0x0020, 0x0001))
  1688. error("#V: Cannot start auto detect");
  1689. for (d = (ushort)-1, i = 0; i != 10; i++) {
  1690. if (!mspread(tv, msp_dem, 0x007e, &d))
  1691. error("#V: Cannot get autodetect info MSP34xG5");
  1692. if (d == 0 || d < 0x800)
  1693. break;
  1694. delay(50);
  1695. }
  1696. if (!mspread(tv, msp_dem, 0x0200, &s))
  1697. error("#V: Cannot get status info MSP34xG5");
  1698. mspvolume(tv, 0, tv->aleft, tv->aright);
  1699. nicam = ((s >> 4) & 2) | ((s >> 9) & 1);
  1700. snprint(tv->ainfo, sizeof tv->ainfo, "%s %s %s",
  1701. mspaformat(d), (s & (1 << 6))? "stereo": "mono",
  1702. nicamstate[nicam]);
  1703. }
  1704. static void
  1705. i2cscan(Tv *tv)
  1706. {
  1707. int i, ack;
  1708. for (i = 0; i < 0x100; i += 2) {
  1709. i2c_start(tv);
  1710. ack = i2c_wr8(tv, i, 0);
  1711. i2c_stop(tv);
  1712. if (ack) {
  1713. print("i2c device @%.2uX\n", i);
  1714. }
  1715. }
  1716. for (i = 0xf0; i != 0xff; i++) {
  1717. i2c_start(tv);
  1718. ack = i2c_wr8(tv, i, 0);
  1719. i2c_stop(tv);
  1720. if (ack)
  1721. print("i2c device may be at @%.2uX\n", i);
  1722. }
  1723. }
  1724. static void
  1725. gpioenable(Tv *tv, ulong mask, ulong data)
  1726. {
  1727. Bt848 *bt848 = tv->bt848;
  1728. bt848->gpioouten = (bt848->gpioouten & mask) | data;
  1729. }
  1730. static void
  1731. gpiowrite(Tv *tv, ulong mask, ulong data)
  1732. {
  1733. Bt848 *bt848 = tv->bt848;
  1734. bt848->gpiodata[0] = (bt848->gpiodata[0] & mask) | data;
  1735. }
  1736. static void
  1737. alteraoutput(Tv *tv)
  1738. {
  1739. if (tv->gpiostate == Gpiooutput)
  1740. return;
  1741. gpioenable(tv, ~0xffffff, 0x56ffff);
  1742. microdelay(10);
  1743. tv->gpiostate = Gpiooutput;
  1744. }
  1745. static void
  1746. alterainput(Tv *tv)
  1747. {
  1748. if (tv->gpiostate == Gpioinput)
  1749. return;
  1750. gpioenable(tv, ~0xffffff, 0x570000);
  1751. microdelay(10);
  1752. tv->gpiostate = Gpioinput;
  1753. }
  1754. static void
  1755. alterareg(Tv *tv, ulong reg)
  1756. {
  1757. if (tv->alterareg == reg)
  1758. return;
  1759. gpiowrite(tv, ~0x56ffff, (reg & 0x54ffff) | tv->alteraclock);
  1760. microdelay(10);
  1761. tv->alterareg = reg;
  1762. }
  1763. static void
  1764. alterawrite(Tv *tv, ulong reg, ushort data)
  1765. {
  1766. alteraoutput(tv);
  1767. alterareg(tv, reg);
  1768. tv->alteraclock ^= 0x20000;
  1769. gpiowrite(tv, ~0x56ffff, (reg & 0x540000) | data | tv->alteraclock);
  1770. microdelay(10);
  1771. }
  1772. static void
  1773. alteraread(Tv *tv, int reg, ushort *data)
  1774. {
  1775. Bt848 *bt848 = tv->bt848;
  1776. if (tv->alterareg != reg) {
  1777. alteraoutput(tv);
  1778. alterareg(tv, reg);
  1779. }
  1780. else {
  1781. gpioenable(tv, ~0xffffff, 0x560000);
  1782. microdelay(10);
  1783. }
  1784. alterainput(tv);
  1785. gpiowrite(tv, ~0x570000, (reg & 0x560000) | tv->alteraclock);
  1786. microdelay(10);
  1787. *data = (ushort)bt848->gpiodata[0];
  1788. microdelay(10);
  1789. }
  1790. static void
  1791. kfirloadu(Tv *tv, uchar *u, int ulen)
  1792. {
  1793. Bt848 *bt848 = tv->bt848;
  1794. int i, j;
  1795. ilock(&tv->kfirlock);
  1796. bt848->gpioouten &= 0xff000000;
  1797. bt848->gpioouten |= gpio_altera_data |
  1798. gpio_altera_clock | gpio_altera_nconfig;
  1799. bt848->gpiodata[0] &= 0xff000000;
  1800. microdelay(10);
  1801. bt848->gpiodata[0] |= gpio_altera_nconfig;
  1802. microdelay(10);
  1803. // Download the microcode
  1804. for (i = 0; i != ulen; i++)
  1805. for (j = 0; j != 8; j++) {
  1806. bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
  1807. if (u[i] & 1)
  1808. bt848->gpiodata[0] |= gpio_altera_data;
  1809. bt848->gpiodata[0] |= gpio_altera_clock;
  1810. u[i] >>= 1;
  1811. }
  1812. bt848->gpiodata[0] &= ~gpio_altera_clock;
  1813. microdelay(100);
  1814. // Initialize.
  1815. for (i = 0; i != 30; i++) {
  1816. bt848->gpiodata[0] &= ~gpio_altera_clock;
  1817. bt848->gpiodata[0] |= gpio_altera_clock;
  1818. }
  1819. bt848->gpiodata[0] &= ~(gpio_altera_clock|gpio_altera_data);
  1820. iunlock(&tv->kfirlock);
  1821. tv->gpiostate = Gpioinit;
  1822. }
  1823. static void
  1824. kfirreset(Tv *tv)
  1825. {
  1826. alterawrite(tv, 0, 0);
  1827. microdelay(10);
  1828. alterawrite(tv, 0x40000, 0);
  1829. microdelay(10);
  1830. alterawrite(tv, 0x40006, 0x80);
  1831. microdelay(10);
  1832. alterawrite(tv, 8, 1);
  1833. microdelay(10);
  1834. alterawrite(tv, 0x40004, 2);
  1835. microdelay(10);
  1836. alterawrite(tv, 4, 3);
  1837. microdelay(3);
  1838. }
  1839. static int
  1840. kfirinitialize(Tv *tv)
  1841. {
  1842. // Initialize parameters?
  1843. tv->gpiostate = Gpioinit;
  1844. tv->alterareg = -1;
  1845. tv->alteraclock = 0x20000;
  1846. kfirloadu(tv, hcwAMC, sizeof hcwAMC);
  1847. kfirreset(tv);
  1848. return 1;
  1849. }