The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/devtv.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 942fc8f7d8a4f9d9abcc4bf86537485e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.