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/dev/video/cxm/cxm.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  * Copyright (c) 2003, 2004, 2005
    3  *      John Wehle <john@feith.com>.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by John Wehle.
   16  * 4. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   22  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   28  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Conexant MPEG-2 Codec driver. Supports the CX23415 / CX23416
   34  * chips that are on the Hauppauge PVR-250 and PVR-350 video
   35  * capture cards.  Currently only the encoder is supported.
   36  *
   37  * This driver was written using the invaluable information
   38  * compiled by The IvyTV Project (ivtv.sourceforge.net).
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/conf.h>
   44 #include <sys/uio.h>
   45 #include <sys/kernel.h>
   46 #include <sys/mman.h>
   47 #include <sys/module.h>
   48 #include <sys/event.h>
   49 #include <sys/proc.h>
   50 #include <sys/signalvar.h>
   51 #include <sys/thread2.h>
   52 #include <sys/vnode.h>
   53 #include <sys/resource.h>
   54 #include <sys/bus.h>
   55 #include <sys/rman.h>
   56 
   57 #include <machine/clock.h>
   58 
   59 #include <dev/video/meteor/ioctl_meteor.h>
   60 #include <dev/video/bktr/ioctl_bt848.h>
   61 
   62 #include <bus/pci/pcireg.h>
   63 #include <bus/pci/pcivar.h>
   64 
   65 #include <dev/video/cxm/cxm.h>
   66 
   67 #include <bus/iicbus/iiconf.h>
   68 
   69 /*
   70  * Various supported device vendors/types and their names.
   71  */
   72 static struct cxm_dev cxm_devs[] = {
   73         { PCI_VENDOR_ICOMPRESSION, PCI_PRODUCT_ICOMPRESSION_ITVC15,
   74                 "Conexant iTVC15 MPEG Coder" },
   75         { PCI_VENDOR_ICOMPRESSION, PCI_PRODUCT_ICOMPRESSION_ITVC16,
   76                 "Conexant iTVC16 MPEG Coder" },
   77         { 0, 0, NULL }
   78 };
   79 
   80 
   81 static int      cxm_probe(device_t dev);
   82 static int      cxm_attach(device_t dev);
   83 static int      cxm_detach(device_t dev);
   84 static int      cxm_shutdown(device_t dev);
   85 static void     cxm_intr(void *arg);
   86 
   87 static void     cxm_child_detached(device_t dev, device_t child);
   88 static int      cxm_read_ivar(device_t bus, device_t dev,
   89                                int index, uintptr_t* val);
   90 static int      cxm_write_ivar(device_t bus, device_t dev,
   91                                 int index, uintptr_t val);
   92 
   93 
   94 static device_method_t cxm_methods[] = {
   95         /* Device interface */
   96         DEVMETHOD(device_probe,         cxm_probe),
   97         DEVMETHOD(device_attach,        cxm_attach),
   98         DEVMETHOD(device_detach,        cxm_detach),
   99         DEVMETHOD(device_shutdown,      cxm_shutdown),
  100 
  101         /* bus interface */
  102         DEVMETHOD(bus_child_detached,   cxm_child_detached),
  103         DEVMETHOD(bus_print_child,      bus_generic_print_child),
  104         DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
  105         DEVMETHOD(bus_read_ivar,        cxm_read_ivar),
  106         DEVMETHOD(bus_write_ivar,       cxm_write_ivar),
  107 
  108         DEVMETHOD_END
  109 };
  110 
  111 static driver_t cxm_driver = {
  112         "cxm",
  113         cxm_methods,
  114         sizeof(struct cxm_softc),
  115 };
  116 
  117 static devclass_t cxm_devclass;
  118 
  119 static  d_open_t        cxm_open;
  120 static  d_close_t       cxm_close;
  121 static  d_read_t        cxm_read;
  122 static  d_ioctl_t       cxm_ioctl;
  123 static  d_kqfilter_t    cxm_kqfilter;
  124 
  125 static void cxm_filter_detach(struct knote *);
  126 static int cxm_filter(struct knote *, long);
  127 
  128 static struct dev_ops cxm_ops = {
  129         { "cxm", 0, 0 },
  130         .d_open =       cxm_open,
  131         .d_close =      cxm_close,
  132         .d_read =       cxm_read,
  133         .d_ioctl =      cxm_ioctl,
  134         .d_kqfilter =   cxm_kqfilter
  135 };
  136 
  137 MODULE_DEPEND(cxm, cxm_iic, 1, 1, 1);
  138 DRIVER_MODULE(cxm, pci, cxm_driver, cxm_devclass, NULL, NULL);
  139 
  140 
  141 static struct cxm_codec_audio_format codec_audio_formats[] = {
  142         { 44100, 0xb8 }, /* 44.1 Khz, MPEG-1 Layer II, 224 kb/s */
  143         { 48000, 0xe9 }  /* 48 Khz, MPEG-1 Layer II, 384 kb/s */
  144 };
  145 
  146 
  147 /*
  148  * Various profiles.
  149  */
  150 static struct cxm_codec_profile vcd_ntsc_profile = {
  151         "MPEG-1 VideoCD NTSC video and MPEG audio",
  152         CXM_FW_STREAM_TYPE_VCD,
  153         30,
  154         352, 240, 480,
  155         { 10, 12, 21 },
  156         12,
  157         0,
  158         { 1, 1150000, 0 },
  159         { 1, 15, 3},
  160         /*
  161          * Spatial filter = Manual, Temporal filter = Manual
  162          * Median filter = Horizontal / Vertical
  163          * Spatial filter value = 1, Temporal filter value = 4
  164          */
  165         { 0, 3, 1, 4 },
  166         44100
  167 };
  168 
  169 static struct cxm_codec_profile vcd_pal_profile = {
  170         "MPEG-1 VideoCD PAL video and MPEG audio",
  171         CXM_FW_STREAM_TYPE_VCD,
  172         25,
  173         352, 288, 576,
  174         { 6, 17, 22 },
  175         8,
  176         0,
  177         { 1, 1150000, 0 },
  178         { 1, 12, 3},
  179         /*
  180          * Spatial filter = Manual, Temporal filter = Manual
  181          * Median filter = Horizontal / Vertical
  182          * Spatial filter value = 1, Temporal filter value = 4
  183          */
  184         { 0, 3, 1, 4 },
  185         44100
  186 };
  187 
  188 static struct cxm_codec_profile svcd_ntsc_profile = {
  189         "MPEG-2 SuperVCD NTSC video and MPEG audio",
  190         CXM_FW_STREAM_TYPE_SVCD,
  191         30,
  192         480, 480, 480,
  193         { 10, 12, 21 },
  194         2,
  195         0,
  196         /* 2.5 Mb/s peak limit to keep bbdmux followed by mplex -f 4 happy */
  197         { 0, 1150000, 2500000 },
  198         { 1, 15, 3},
  199         /*
  200          * Spatial filter = Manual, Temporal filter = Manual
  201          * Median filter = Horizontal / Vertical
  202          * Spatial filter value = 1, Temporal filter value = 4
  203          */
  204         { 0, 3, 1, 4 },
  205         44100
  206 };
  207 
  208 static struct cxm_codec_profile svcd_pal_profile = {
  209         "MPEG-2 SuperVCD PAL video and MPEG audio",
  210         CXM_FW_STREAM_TYPE_SVCD,
  211         25,
  212         480, 576, 576,
  213         { 6, 17, 22 },
  214         2,
  215         0,
  216         /* 2.5 Mb/s peak limit to keep bbdmux followed by mplex -f 4 happy */
  217         { 0, 1150000, 2500000 },
  218         { 1, 12, 3},
  219         /*
  220          * Spatial filter = Manual, Temporal filter = Manual
  221          * Median filter = Horizontal / Vertical
  222          * Spatial filter value = 1, Temporal filter value = 4
  223          */
  224         { 0, 3, 1, 4 },
  225         44100
  226 };
  227 
  228 static struct cxm_codec_profile dvd_half_d1_ntsc_profile = {
  229         "MPEG-2 DVD NTSC video and MPEG audio",
  230         CXM_FW_STREAM_TYPE_DVD,
  231         30,
  232         352, 480, 480,
  233         { 10, 12, 21 },
  234         2,
  235         0,
  236         { 0, 4000000, 4520000 }, /* 4 hours on 8.54 GB media */
  237         { 1, 15, 3},
  238         /*
  239          * Spatial filter = Manual, Temporal filter = Manual
  240          * Median filter = Horizontal / Vertical
  241          * Spatial filter value = 1, Temporal filter value = 4
  242          */
  243         { 0, 3, 1, 4 },
  244         48000
  245 };
  246 
  247 static struct cxm_codec_profile dvd_half_d1_pal_profile = {
  248         "MPEG-2 DVD PAL video and MPEG audio",
  249         CXM_FW_STREAM_TYPE_DVD,
  250         25,
  251         352, 576, 576,
  252         { 6, 17, 22 },
  253         2,
  254         0,
  255         { 0, 4000000, 4520000 }, /* 4 hours on 8.54 GB media */
  256         { 1, 12, 3},
  257         /*
  258          * Spatial filter = Manual, Temporal filter = Manual
  259          * Median filter = Horizontal / Vertical
  260          * Spatial filter value = 1, Temporal filter value = 4
  261          */
  262         { 0, 3, 1, 4 },
  263         48000
  264 };
  265 
  266 static struct cxm_codec_profile dvd_full_d1_ntsc_profile = {
  267         "MPEG-2 DVD NTSC video and MPEG audio",
  268         CXM_FW_STREAM_TYPE_DVD,
  269         30,
  270         720, 480, 480,
  271         { 10, 12, 21 },
  272         2,
  273         0,
  274         /* 9.52 Mb/s peak limit to keep bbdmux followed by mplex -f 8 happy */
  275         { 0, 9000000, 9520000 }, /* 1 hour on 4.7 GB media */
  276         { 1, 15, 3},
  277         /*
  278          * Spatial filter = Manual, Temporal filter = Manual
  279          * Median filter = Horizontal / Vertical
  280          * Spatial filter value = 1, Temporal filter value = 4
  281          */
  282         { 0, 3, 1, 4 },
  283         48000
  284 };
  285 
  286 static struct cxm_codec_profile dvd_full_d1_pal_profile = {
  287         "MPEG-2 DVD PAL video and MPEG audio",
  288         CXM_FW_STREAM_TYPE_DVD,
  289         25,
  290         720, 576, 576,
  291         { 6, 17, 22 },
  292         2,
  293         0,
  294         /* 9.52 Mb/s peak limit to keep bbdmux followed by mplex -f 8 happy */
  295         { 0, 9000000, 9520000 }, /* 1 hour on 4.7 GB media */
  296         { 1, 12, 3},
  297         /*
  298          * Spatial filter = Manual, Temporal filter = Manual
  299          * Median filter = Horizontal / Vertical
  300          * Spatial filter value = 1, Temporal filter value = 4
  301          */
  302         { 0, 3, 1, 4 },
  303         48000
  304 };
  305 
  306 
  307 static const struct cxm_codec_profile
  308 *codec_profiles[] = {
  309         &vcd_ntsc_profile,
  310         &vcd_pal_profile,
  311         &svcd_ntsc_profile,
  312         &svcd_pal_profile,
  313         &dvd_half_d1_ntsc_profile,
  314         &dvd_half_d1_pal_profile,
  315         &dvd_full_d1_ntsc_profile,
  316         &dvd_full_d1_pal_profile
  317 };
  318 
  319 
  320 static unsigned int
  321 cxm_queue_firmware_command(struct cxm_softc *sc,
  322                             enum cxm_mailbox_name mbx_name, uint32_t cmd,
  323                             uint32_t *parameters, unsigned int nparameters)
  324 {
  325         unsigned int i;
  326         unsigned int mailbox;
  327         uint32_t completed_command;
  328         uint32_t flags;
  329 
  330         if (nparameters > CXM_MBX_MAX_PARAMETERS) {
  331                 device_printf(sc->dev, "too many parameters for mailbox\n");
  332                 return -1;
  333         }
  334 
  335         mailbox = 0;
  336 
  337         switch (mbx_name) {
  338         case cxm_dec_mailbox:
  339                 mailbox = sc->dec_mbx
  340                           + CXM_MBX_FW_CMD_MAILBOX *sizeof(struct cxm_mailbox);
  341                 break;
  342 
  343         case cxm_enc_mailbox:
  344                 mailbox = sc->enc_mbx
  345                           + CXM_MBX_FW_CMD_MAILBOX *sizeof(struct cxm_mailbox);
  346                 break;
  347 
  348         default:
  349                 return -1;
  350         }
  351 
  352         crit_enter();
  353         for (i = 0; i < CXM_MBX_FW_CMD_MAILBOXES; i++) {
  354                 flags = CSR_READ_4(sc,
  355                                    mailbox
  356                                    + offsetof(struct cxm_mailbox, flags));
  357                 if (!(flags & CXM_MBX_FLAG_IN_USE))
  358                         break;
  359 
  360                 /*
  361                  * Mail boxes containing certain completed commands
  362                  * for which the results are never needed can be reused.
  363                  */
  364 
  365                 if ((flags & (CXM_MBX_FLAG_DRV_DONE | CXM_MBX_FLAG_FW_DONE))
  366                     == (CXM_MBX_FLAG_DRV_DONE | CXM_MBX_FLAG_FW_DONE)) {
  367                         completed_command
  368                          = CSR_READ_4(sc,
  369                                       mailbox
  370                                       + offsetof(struct cxm_mailbox, command));
  371 
  372                         /*
  373                          * DMA results are always check by reading the
  374                          * DMA status register ... never by checking
  375                          * the mailbox after the command has completed.
  376                          */
  377 
  378                         if (completed_command == CXM_FW_CMD_SCHED_DMA_TO_HOST)
  379                                 break;
  380                 }
  381 
  382                 mailbox += sizeof(struct cxm_mailbox);
  383         }
  384 
  385         if (i >= CXM_MBX_FW_CMD_MAILBOXES) {
  386                 crit_exit();
  387                 return -1;
  388         }
  389 
  390         CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags),
  391                     CXM_MBX_FLAG_IN_USE);
  392 
  393         /*
  394          * PCI writes may be buffered so force the
  395          * write to complete by reading the last
  396          * location written.
  397          */
  398 
  399         CSR_READ_4(sc, mailbox + offsetof(struct cxm_mailbox, flags));
  400 
  401         crit_exit();
  402 
  403         CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, command), cmd);
  404         CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, timeout),
  405                     CXM_FW_STD_TIMEOUT);
  406 
  407         for (i = 0; i < nparameters; i++)
  408                 CSR_WRITE_4(sc,
  409                             mailbox
  410                             + offsetof(struct cxm_mailbox, parameters)
  411                             + i * sizeof(uint32_t),
  412                             *(parameters + i));
  413 
  414         for (; i < CXM_MBX_MAX_PARAMETERS; i++)
  415                 CSR_WRITE_4(sc,
  416                             mailbox
  417                             + offsetof(struct cxm_mailbox, parameters)
  418                             + i * sizeof(uint32_t), 0);
  419 
  420         CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags),
  421                     CXM_MBX_FLAG_IN_USE | CXM_MBX_FLAG_DRV_DONE);
  422 
  423         return mailbox;
  424 }
  425 
  426 
  427 static int
  428 cxm_firmware_command(struct cxm_softc *sc,
  429                       enum cxm_mailbox_name mbx_name, uint32_t cmd,
  430                       uint32_t *parameters, unsigned int nparameters)
  431 {
  432         const char *wmesg;
  433         unsigned int *bmp;
  434         unsigned int i;
  435         unsigned int mailbox;
  436         uint32_t flags;
  437         uint32_t result;
  438 
  439         bmp = NULL;
  440         wmesg = "";
  441 
  442         switch (mbx_name) {
  443         case cxm_dec_mailbox:
  444                 bmp = &sc->dec_mbx;
  445                 wmesg = "cxmdfw";
  446                 break;
  447 
  448         case cxm_enc_mailbox:
  449                 bmp = &sc->enc_mbx;
  450                 wmesg = "cxmefw";
  451                 break;
  452 
  453         default:
  454                 return -1;
  455         }
  456 
  457         mailbox = cxm_queue_firmware_command(sc, mbx_name, cmd,
  458                                              parameters, nparameters);
  459         if (mailbox == -1) {
  460                 device_printf(sc->dev, "no free mailboxes\n");
  461                 return -1;
  462         }
  463 
  464         /* Give the firmware a chance to start processing the request */
  465         tsleep(bmp, 0, wmesg, hz / 100);
  466 
  467         for (i = 0; i < 100; i++) {
  468                 flags = CSR_READ_4(sc,
  469                                    mailbox
  470                                    + offsetof(struct cxm_mailbox, flags));
  471                 if ((flags & CXM_MBX_FLAG_FW_DONE))
  472                         break;
  473 
  474                 /* Wait for 10ms */
  475                 tsleep(bmp, 0, wmesg, hz / 100);
  476         }
  477 
  478         if (i >= 100) {
  479                 device_printf(sc->dev, "timeout\n");
  480                 return -1;
  481         }
  482 
  483         result = CSR_READ_4(sc,
  484                             mailbox
  485                             + offsetof(struct cxm_mailbox, result));
  486 
  487         for (i = 0; i < nparameters; i++)
  488                 *(parameters + i)
  489                   = CSR_READ_4(sc,
  490                                mailbox
  491                                + offsetof(struct cxm_mailbox, parameters)
  492                                + i * sizeof(uint32_t));
  493 
  494         CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags), 0);
  495 
  496         return result == 0 ? 0 : -1;
  497 }
  498 
  499 
  500 static int
  501 cxm_firmware_command_nosleep(struct cxm_softc *sc,
  502                               enum cxm_mailbox_name mbx_name, uint32_t cmd,
  503                               uint32_t *parameters, unsigned int nparameters)
  504 {
  505         unsigned int i;
  506         unsigned int mailbox;
  507         uint32_t flags;
  508         uint32_t result;
  509 
  510         for (i = 0; i < 100; i++) {
  511                 mailbox = cxm_queue_firmware_command(sc, mbx_name, cmd,
  512                                                      parameters, nparameters);
  513                 if (mailbox != -1)
  514                         break;
  515 
  516                 /* Wait for 10ms */
  517                 DELAY(10000);
  518                 }
  519 
  520         if (i >= 100) {
  521                 device_printf(sc->dev, "no free mailboxes\n");
  522                 return -1;
  523         }
  524 
  525         /* Give the firmware a chance to start processing the request */
  526         DELAY(10000);
  527 
  528         for (i = 0; i < 100; i++) {
  529                 flags = CSR_READ_4(sc,
  530                                    mailbox
  531                                    + offsetof(struct cxm_mailbox, flags));
  532                 if ((flags & CXM_MBX_FLAG_FW_DONE))
  533                         break;
  534 
  535                 /* Wait for 10ms */
  536                 DELAY(10000);
  537         }
  538 
  539         if (i >= 100) {
  540                 device_printf(sc->dev, "timeout\n");
  541                 return -1;
  542         }
  543 
  544         result = CSR_READ_4(sc,
  545                             mailbox
  546                             + offsetof(struct cxm_mailbox, result));
  547 
  548         for (i = 0; i < nparameters; i++)
  549                 *(parameters + i)
  550                   = CSR_READ_4(sc,
  551                                mailbox
  552                                + offsetof(struct cxm_mailbox, parameters)
  553                                + i * sizeof(uint32_t));
  554 
  555         CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags), 0);
  556 
  557         return result == 0 ? 0 : -1;
  558 }
  559 
  560 
  561 static int
  562 cxm_stop_firmware(struct cxm_softc *sc)
  563 {
  564 
  565         if (cxm_firmware_command_nosleep(sc, cxm_enc_mailbox,
  566                                          CXM_FW_CMD_ENC_HALT_FW, NULL, 0) < 0)
  567                 return -1;
  568 
  569         if (sc->type == cxm_iTVC15_type
  570             && cxm_firmware_command_nosleep(sc, cxm_dec_mailbox,
  571                                             CXM_FW_CMD_DEC_HALT_FW,
  572                                             NULL, 0) < 0)
  573                 return -1;
  574 
  575         /* Wait for 10ms */
  576         DELAY(10000);
  577 
  578         return 0;
  579 }
  580 
  581 
  582 static void
  583 cxm_set_irq_mask(struct cxm_softc *sc, uint32_t mask)
  584 {
  585         crit_enter();
  586 
  587         CSR_WRITE_4(sc, CXM_REG_IRQ_MASK, mask);
  588 
  589         /*
  590          * PCI writes may be buffered so force the
  591          * write to complete by reading the last
  592          * location written.
  593          */
  594 
  595         CSR_READ_4(sc, CXM_REG_IRQ_MASK);
  596 
  597         sc->irq_mask = mask;
  598 
  599         crit_exit();
  600 }
  601 
  602 
  603 static void
  604 cxm_set_irq_status(struct cxm_softc *sc, uint32_t status)
  605 {
  606 
  607         CSR_WRITE_4(sc, CXM_REG_IRQ_STATUS, status);
  608 
  609         /*
  610          * PCI writes may be buffered so force the
  611          * write to complete by reading the last
  612          * location written.
  613          */
  614 
  615         CSR_READ_4(sc, CXM_REG_IRQ_STATUS);
  616 }
  617 
  618 
  619 static int
  620 cxm_stop_hardware(struct cxm_softc *sc)
  621 {
  622         if (sc->cxm_iic) {
  623                 if (cxm_saa7115_mute(sc) < 0)
  624                         return -1;
  625                 if (cxm_msp_mute(sc) < 0)
  626                         return -1;
  627         }
  628 
  629         /* Halt the firmware */
  630         if (sc->enc_mbx != -1) {
  631                 if (cxm_stop_firmware(sc) < 0)
  632                         return -1;
  633         }
  634 
  635         /* Mask all interrupts */
  636         cxm_set_irq_mask(sc, 0xffffffff);
  637 
  638         /* Stop VDM */
  639         CSR_WRITE_4(sc, CXM_REG_VDM, CXM_CMD_VDM_STOP);
  640 
  641         /* Stop AO */
  642         CSR_WRITE_4(sc, CXM_REG_AO, CXM_CMD_AO_STOP);
  643 
  644         /* Ping (?) APU */
  645         CSR_WRITE_4(sc, CXM_REG_APU, CXM_CMD_APU_PING);
  646 
  647         /* Stop VPU */
  648         CSR_WRITE_4(sc, CXM_REG_VPU, sc->type == cxm_iTVC15_type
  649                                         ? CXM_CMD_VPU_STOP15
  650                                         : CXM_CMD_VPU_STOP16);
  651 
  652         /* Reset Hw Blocks */
  653         CSR_WRITE_4(sc, CXM_REG_HW_BLOCKS, CXM_CMD_HW_BLOCKS_RST);
  654 
  655         /* Stop SPU */
  656         CSR_WRITE_4(sc, CXM_REG_SPU, CXM_CMD_SPU_STOP);
  657 
  658         /* Wait for 10ms */
  659         DELAY(10000);
  660 
  661         return 0;
  662 }
  663 
  664 
  665 static int
  666 cxm_download_firmware(struct cxm_softc *sc)
  667 {
  668         unsigned int i;
  669         const uint32_t *fw;
  670 
  671         /* Check if firmware is compiled in */
  672         if (strncmp((const char *)cxm_enc_fw, "NOFW", 4) == 0) {
  673                 device_printf(sc->dev, "encoder firmware not compiled in\n");
  674                 return -1;
  675         } else if (strncmp((const char *)cxm_dec_fw, "NOFW", 4) == 0) {
  676                 device_printf(sc->dev, "decoder firmware not compiled in\n");
  677                 return -1;
  678         }
  679 
  680         /* Download the encoder firmware */
  681         fw = (const uint32_t *)cxm_enc_fw;
  682         for (i = 0; i < CXM_FW_SIZE; i += sizeof(*fw))
  683                 CSR_WRITE_4(sc, CXM_MEM_ENC + i, *fw++);
  684 
  685         /* Download the decoder firmware */
  686         if (sc->type == cxm_iTVC15_type) {
  687                 fw = (const uint32_t *)cxm_dec_fw;
  688                 for (i = 0; i < CXM_FW_SIZE; i += sizeof(*fw))
  689                         CSR_WRITE_4(sc, CXM_MEM_DEC + i, *fw++);
  690         }
  691 
  692         return 0;
  693 }
  694 
  695 
  696 static int
  697 cxm_init_hardware(struct cxm_softc *sc)
  698 {
  699         unsigned int i;
  700         unsigned int mailbox;
  701         uint32_t parameter;
  702 
  703         if (cxm_stop_hardware(sc) < 0)
  704                 return -1;
  705 
  706         /* Initialize encoder SDRAM pre-charge */
  707         CSR_WRITE_4(sc, CXM_REG_ENC_SDRAM_PRECHARGE,
  708                         CXM_CMD_SDRAM_PRECHARGE_INIT);
  709 
  710         /* Initialize encoder SDRAM refresh to 1us */
  711         CSR_WRITE_4(sc, CXM_REG_ENC_SDRAM_REFRESH,
  712                         CXM_CMD_SDRAM_REFRESH_INIT);
  713 
  714         /* Initialize decoder SDRAM pre-charge */
  715         CSR_WRITE_4(sc, CXM_REG_DEC_SDRAM_PRECHARGE,
  716                         CXM_CMD_SDRAM_PRECHARGE_INIT);
  717 
  718         /* Initialize decoder SDRAM refresh to 1us */
  719         CSR_WRITE_4(sc, CXM_REG_DEC_SDRAM_REFRESH,
  720                         CXM_CMD_SDRAM_REFRESH_INIT);
  721 
  722         /* Wait for 600ms */
  723         DELAY(600000);
  724 
  725         if (cxm_download_firmware(sc) < 0)
  726                 return -1;
  727 
  728         /* Enable SPU */
  729         CSR_WRITE_4(sc, CXM_REG_SPU,
  730                         CSR_READ_4(sc, CXM_REG_SPU) & CXM_MASK_SPU_ENABLE);
  731 
  732         /* Wait for 1 second */
  733         DELAY(1000000);
  734 
  735         /* Enable VPU */
  736         CSR_WRITE_4(sc, CXM_REG_VPU,
  737                         CSR_READ_4(sc, CXM_REG_VPU)
  738                         & (sc->type == cxm_iTVC15_type
  739                                 ? CXM_MASK_VPU_ENABLE15
  740                                 : CXM_MASK_VPU_ENABLE16));
  741 
  742         /* Wait for 1 second */
  743         DELAY(1000000);
  744 
  745         /* Locate encoder mailbox */
  746         mailbox = CXM_MEM_ENC;
  747         for (i = 0; i < CXM_MEM_ENC_SIZE; i += 0x100)
  748                 if (CSR_READ_4(sc, mailbox + i) == 0x12345678
  749                     && CSR_READ_4(sc, mailbox + i + 4) == 0x34567812
  750                     && CSR_READ_4(sc, mailbox + i + 8) == 0x56781234
  751                     && CSR_READ_4(sc, mailbox + i + 12) == 0x78123456)
  752                         break;
  753 
  754         if (i >= CXM_MEM_ENC_SIZE)
  755                 return -1;
  756 
  757         sc->enc_mbx = mailbox + i + 16;
  758 
  759         /* Locate decoder mailbox */
  760         if (sc->type == cxm_iTVC15_type) {
  761                 mailbox = CXM_MEM_DEC;
  762                 for (i = 0; i < CXM_MEM_DEC_SIZE; i += 0x100)
  763                         if (CSR_READ_4(sc, mailbox + i) == 0x12345678
  764                             && CSR_READ_4(sc, mailbox + i + 4) == 0x34567812
  765                             && CSR_READ_4(sc, mailbox + i + 8) == 0x56781234
  766                             && CSR_READ_4(sc, mailbox + i + 12) == 0x78123456)
  767                                 break;
  768 
  769                 if (i >= CXM_MEM_DEC_SIZE)
  770                         return -1;
  771 
  772                 sc->dec_mbx = mailbox + i + 16;
  773         }
  774 
  775         /* Get encoder firmware version */
  776         parameter = 0;
  777         if (cxm_firmware_command_nosleep(sc, cxm_enc_mailbox,
  778                                          CXM_FW_CMD_ENC_GET_FW_VER,
  779                                          &parameter, 1) < 0)
  780                 return -1;
  781 
  782         device_printf(sc->dev, "encoder firmware version %#x\n",
  783             (unsigned int)parameter);
  784 
  785         /* Get decoder firmware version */
  786         if (sc->type == cxm_iTVC15_type) {
  787                 parameter = 0;
  788                 if (cxm_firmware_command_nosleep(sc, cxm_dec_mailbox,
  789                                                  CXM_FW_CMD_DEC_GET_FW_VER,
  790                                                  &parameter, 1) < 0)
  791                         return -1;
  792 
  793                 device_printf(sc->dev, "decoder firmware version %#x\n",
  794                     (unsigned int)parameter);
  795         }
  796 
  797         return 0;
  798 }
  799 
  800 
  801 static int
  802 cxm_configure_encoder(struct cxm_softc *sc)
  803 {
  804         int fps;
  805         unsigned int i;
  806         uint32_t parameters[12];
  807         const struct cxm_codec_profile *cpp;
  808 
  809         if (sc->source == cxm_fm_source)
  810                 switch (cxm_tuner_selected_channel_set(sc)) {
  811                 case CHNLSET_NABCST:
  812                 case CHNLSET_CABLEIRC:
  813                 case CHNLSET_JPNBCST:
  814                 case CHNLSET_JPNCABLE:
  815                         fps = 30;
  816                         break;
  817 
  818                 default:
  819                         fps = 25;
  820                         break;
  821                 }
  822         else
  823                 fps = cxm_saa7115_detected_fps(sc);
  824 
  825         if (fps < 0)
  826                 return -1;
  827 
  828         if (sc->profile->fps != fps) {
  829 
  830                 /*
  831                  * Pick a profile with the correct fps using the
  832                  * chosen stream type and width to decide between
  833                  * the VCD, SVCD, or DVD profiles.
  834                  */
  835 
  836                 for (i = 0; i < NUM_ELEMENTS(codec_profiles); i++)
  837                         if (codec_profiles[i]->fps == fps
  838                             && codec_profiles[i]->stream_type
  839                                == sc->profile->stream_type
  840                             && codec_profiles[i]->width == sc->profile->width)
  841                                 break;
  842 
  843                 if (i >= NUM_ELEMENTS(codec_profiles))
  844                         return -1;
  845 
  846                 sc->profile = codec_profiles[i];
  847         }
  848 
  849         cpp = sc->profile;
  850 
  851         if (cxm_saa7115_configure(sc,
  852                                   cpp->width, cpp->source_height, fps,
  853                                   cpp->audio_sample_rate) < 0)
  854                 return -1;
  855 
  856         /* assign dma block len */
  857         parameters[0] = 1; /* Transfer block size = 1 */
  858         parameters[1] = 1; /* Units = 1 (frames) */
  859         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  860                                  CXM_FW_CMD_ASSIGN_DMA_BLOCKLEN,
  861                                  parameters, 2) != 0)
  862                 return -1;
  863 
  864 
  865         /* assign program index info */
  866         parameters[0] = 0; /* Picture mask = 0 (don't generate index) */
  867         parameters[1] = 0; /* Num_req = 0 */
  868         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  869                                  CXM_FW_CMD_ASSIGN_PGM_INDEX_INFO,
  870                                  parameters, 2) != 0)
  871                 return -1;
  872 
  873         /* assign stream type */
  874         parameters[0] = cpp->stream_type;
  875         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  876                                  CXM_FW_CMD_ASSIGN_STREAM_TYPE,
  877                                  parameters, 1) != 0)
  878                 return -1;
  879 
  880         /* assign output port */
  881         parameters[0] = 0; /* 0 (Memory) */
  882         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  883                                  CXM_FW_CMD_ASSIGN_OUTPUT_PORT,
  884                                  parameters, 1) != 0)
  885                 return -1;
  886 
  887         /* assign framerate */
  888         parameters[0] = cpp->fps == 30 ? 0 : 1;
  889         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  890                                  CXM_FW_CMD_ASSIGN_FRAME_RATE,
  891                                  parameters, 1) != 0)
  892                 return -1;
  893 
  894         /* assign frame size */
  895         parameters[0] = cpp->height;
  896         parameters[1] = cpp->width;
  897         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  898                                  CXM_FW_CMD_ASSIGN_FRAME_SIZE,
  899                                  parameters, 2) != 0)
  900                 return -1;
  901 
  902         /* assign aspect ratio */
  903         parameters[0] = cpp->aspect;
  904         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  905                                  CXM_FW_CMD_ASSIGN_ASPECT_RATIO,
  906                                  parameters, 1) != 0)
  907                 return -1;
  908 
  909         /* assign bitrates */
  910         parameters[0] = cpp->bitrate.mode;
  911         parameters[1] = cpp->bitrate.average;
  912         parameters[2] = cpp->bitrate.peak / 400;
  913         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  914                                  CXM_FW_CMD_ASSIGN_BITRATES,
  915                                  parameters, 3) != 0)
  916                 return -1;
  917 
  918         /* assign gop closure */
  919         parameters[0] = cpp->gop.closure;
  920         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  921                                  CXM_FW_CMD_ASSIGN_GOP_CLOSURE,
  922                                  parameters, 1) != 0)
  923                 return -1;
  924 
  925         /* assign gop properties */
  926         parameters[0] = cpp->gop.frames;
  927         parameters[1] = cpp->gop.bframes;
  928         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  929                                  CXM_FW_CMD_ASSIGN_GOP_PROPERTIES,
  930                                  parameters, 2) != 0)
  931                 return -1;
  932 
  933         /* assign 3 2 pulldown */
  934         parameters[0] = cpp->pulldown;
  935         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  936                                  CXM_FW_CMD_ASSIGN_3_2_PULLDOWN,
  937                                  parameters, 1) != 0)
  938                 return -1;
  939 
  940         /* assign dnr filter mode */
  941         parameters[0] = cpp->dnr.mode;
  942         parameters[1] = cpp->dnr.type;
  943         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  944                                  CXM_FW_CMD_ASSIGN_DNR_FILTER_MODE,
  945                                  parameters, 2) != 0)
  946                 return -1;
  947 
  948         /* assign dnr filter props */
  949         parameters[0] = cpp->dnr.spatial;
  950         parameters[1] = cpp->dnr.temporal;
  951         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  952                                  CXM_FW_CMD_ASSIGN_DNR_FILTER_PROPERTIES,
  953                                  parameters, 2) != 0)
  954                 return -1;
  955 
  956         /*
  957          * assign audio properties
  958          */
  959 
  960         for (i = 0; i < NUM_ELEMENTS(codec_audio_formats); i++)
  961                 if (codec_audio_formats[i].sample_rate
  962                     == cpp->audio_sample_rate)
  963                         break;
  964 
  965         if (i >= NUM_ELEMENTS(codec_audio_formats))
  966                 return -1;
  967 
  968         parameters[0] = codec_audio_formats[i].format;
  969         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  970                                  CXM_FW_CMD_ASSIGN_AUDIO_PROPERTIES,
  971                                  parameters, 1) != 0)
  972                 return -1;
  973 
  974         /* assign coring levels */
  975         parameters[0] = 0; /* luma_h */
  976         parameters[1] = 255; /* luma_l */
  977         parameters[2] = 0; /* chroma_h */
  978         parameters[3] = 255; /* chroma_l */
  979         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  980                                  CXM_FW_CMD_ASSIGN_CORING_LEVELS,
  981                                  parameters, 4) != 0)
  982                 return -1;
  983 
  984         /* assign spatial filter type */
  985         parameters[0] = 3; /* Luminance filter = 3 (2D H/V Separable) */
  986         parameters[1] = 1; /* Chrominance filter = 1 (1D Horizontal) */
  987         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  988                                  CXM_FW_CMD_ASSIGN_SPATIAL_FILTER_TYPE,
  989                                  parameters, 2) != 0)
  990                 return -1;
  991 
  992         /* assign frame drop rate */
  993         parameters[0] = 0;
  994         if (cxm_firmware_command(sc, cxm_enc_mailbox,
  995                                  CXM_FW_CMD_ASSIGN_FRAME_DROP_RATE,
  996                                  parameters, 1) != 0)
  997                 return -1;
  998 
  999         /* assign placeholder */
 1000         parameters[0] = 0; /* type = 0 (Extension / UserData) */
 1001         parameters[1] = 0; /* period */
 1002         parameters[2] = 0; /* size_t */
 1003         parameters[3] = 0; /* arg0 */
 1004         parameters[4] = 0; /* arg1 */
 1005         parameters[5] = 0; /* arg2 */
 1006         parameters[6] = 0; /* arg3 */
 1007         parameters[7] = 0; /* arg4 */
 1008         parameters[8] = 0; /* arg5 */
 1009         parameters[9] = 0; /* arg6 */
 1010         parameters[10] = 0; /* arg7 */
 1011         parameters[11] = 0; /* arg8 */
 1012         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1013                                  CXM_FW_CMD_ASSIGN_PLACEHOLDER,
 1014                                  parameters, 12) != 0)
 1015                 return -1;
 1016 
 1017         /* assign VBI properties */
 1018         parameters[0] = 0xbd04; /* mode = 0 (sliced), stream and user data */
 1019         parameters[1] = 0; /* frames per interrupt (only valid in raw mode) */
 1020         parameters[2] = 0; /* total raw VBI frames (only valid in raw mode) */
 1021         parameters[3] = 0x25256262; /* ITU 656 start codes (saa7115 table 24)*/
 1022         parameters[4] = 0x38387f7f; /* ITU 656 stop codes (saa7115 table 24) */
 1023         parameters[5] = cpp->vbi.nlines; /* lines per frame */
 1024         parameters[6] = 1440; /* bytes per line = 720 pixels */
 1025         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1026                                  CXM_FW_CMD_ASSIGN_VBI_PROPERTIES,
 1027                                  parameters, 7) != 0)
 1028                 return -1;
 1029 
 1030         /* assign VBI lines */
 1031         parameters[0] = 0xffffffff; /* all lines */
 1032         parameters[1] = 0; /* disable VBI features */
 1033         parameters[2] = 0;
 1034         parameters[3] = 0;
 1035         parameters[4] = 0;
 1036         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1037                                  CXM_FW_CMD_ASSIGN_VBI_LINE,
 1038                                  parameters, 5) != 0)
 1039                 return -1;
 1040 
 1041         /* assign number of lines in fields 1 and 2 */
 1042         parameters[0] = cpp->source_height / 2 + cpp->vbi.nlines;
 1043         parameters[1] = cpp->source_height / 2 + cpp->vbi.nlines;
 1044         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1045                                  CXM_FW_CMD_ASSIGN_NUM_VSYNC_LINES,
 1046                                  parameters, 2) != 0)
 1047                 return -1;
 1048 
 1049         return 0;
 1050 }
 1051 
 1052 
 1053 static int
 1054 cxm_start_encoder(struct cxm_softc *sc)
 1055 {
 1056         uint32_t parameters[4];
 1057         uint32_t subtype;
 1058         uint32_t type;
 1059 
 1060 
 1061         if (sc->encoding)
 1062                 return 0;
 1063 
 1064         if (cxm_configure_encoder(sc) < 0)
 1065                 return -1;
 1066 
 1067         /* Mute the video input if necessary. */
 1068         parameters[0] = sc->source == cxm_fm_source ? 1 : 0;
 1069         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1070                                  CXM_FW_CMD_MUTE_VIDEO_INPUT,
 1071                                  parameters, 1) != 0)
 1072                 return -1;
 1073 
 1074         /* Clear pending encoder interrupts (which are currently masked) */
 1075         cxm_set_irq_status(sc, CXM_IRQ_ENC);
 1076 
 1077         /* Enable event notification */
 1078         parameters[0] = 0; /* Event = 0 (refresh encoder input) */
 1079         parameters[1] = 1; /* Notification = 1 (enable) */
 1080         parameters[2] = 0x10000000; /* Interrupt bit */
 1081         parameters[3] = -1; /* Mailbox = -1 (no mailbox) */
 1082         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1083                                  CXM_FW_CMD_ENC_EVENT_NOTIFICATION,
 1084                                  parameters, 4) != 0)
 1085                 return -1;
 1086 
 1087         if (cxm_saa7115_mute(sc) < 0)
 1088                 return -1;
 1089         if (cxm_msp_mute(sc) < 0)
 1090                 return -1;
 1091 
 1092         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1093                                  CXM_FW_CMD_INITIALIZE_VIDEO_INPUT,
 1094                                  NULL, 0) < 0)
 1095                 return -1;
 1096 
 1097         if (cxm_saa7115_unmute(sc) < 0)
 1098                 return -1;
 1099         if (cxm_msp_unmute(sc) < 0)
 1100                 return -1;
 1101 
 1102         /* Wait for 100ms */
 1103         tsleep(&sc->encoding, 0, "cxmce", hz / 10);
 1104 
 1105         type = sc->mpeg ? CXM_FW_CAPTURE_STREAM_TYPE_MPEG
 1106                         : CXM_FW_CAPTURE_STREAM_TYPE_RAW;
 1107         subtype = ((sc->mpeg || sc->source == cxm_fm_source)
 1108                    ? CXM_FW_CAPTURE_STREAM_PCM_AUDIO : 0)
 1109                   | ((sc->mpeg || sc->source != cxm_fm_source)
 1110                      ? CXM_FW_CAPTURE_STREAM_YUV : 0);
 1111 
 1112         /* Start the encoder */
 1113         parameters[0] = type;
 1114         parameters[1] = subtype;
 1115         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1116                                  CXM_FW_CMD_BEGIN_CAPTURE, parameters, 2) != 0)
 1117                 return -1;
 1118 
 1119         sc->enc_pool.offset = 0;
 1120         sc->enc_pool.read = 0;
 1121         sc->enc_pool.write = 0;
 1122 
 1123         sc->encoding_eos = 0;
 1124 
 1125         sc->encoding = 1;
 1126 
 1127         /* Enable interrupts */
 1128         cxm_set_irq_mask(sc, sc->irq_mask & ~CXM_IRQ_ENC);
 1129 
 1130         return 0;
 1131 }
 1132 
 1133 
 1134 static int
 1135 cxm_stop_encoder(struct cxm_softc *sc)
 1136 {
 1137         uint32_t parameters[4];
 1138         uint32_t subtype;
 1139         uint32_t type;
 1140 
 1141         if (!sc->encoding)
 1142                 return 0;
 1143 
 1144         type = sc->mpeg ? CXM_FW_CAPTURE_STREAM_TYPE_MPEG
 1145                         : CXM_FW_CAPTURE_STREAM_TYPE_RAW;
 1146         subtype = ((sc->mpeg || sc->source == cxm_fm_source)
 1147                    ? CXM_FW_CAPTURE_STREAM_PCM_AUDIO : 0)
 1148                   | ((sc->mpeg || sc->source != cxm_fm_source)
 1149                      ? CXM_FW_CAPTURE_STREAM_YUV : 0);
 1150 
 1151         /* Stop the encoder */
 1152         parameters[0] = sc->mpeg ? 0 : 1; /* When = 0 (end of GOP) */
 1153         parameters[1] = type;
 1154         parameters[2] = subtype;
 1155         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1156                                  CXM_FW_CMD_END_CAPTURE, parameters, 3) != 0)
 1157                 return -1;
 1158 
 1159         /* Wait for up to 1 second */
 1160         crit_enter();
 1161         if (!sc->encoding_eos)
 1162                 tsleep(&sc->encoding_eos, 0, "cxmeos", hz);
 1163         crit_exit();
 1164 
 1165         if (sc->mpeg && !sc->encoding_eos)
 1166                 device_printf(sc->dev, "missing encoder EOS\n");
 1167 
 1168         /* Disable event notification */
 1169         parameters[0] = 0; /* Event = 0 (refresh encoder input) */
 1170         parameters[1] = 0; /* Notification = 0 (disable) */
 1171         parameters[2] = 0x10000000; /* Interrupt bit */
 1172         parameters[3] = -1; /* Mailbox = -1 (no mailbox) */
 1173         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1174                                  CXM_FW_CMD_ENC_EVENT_NOTIFICATION,
 1175                                  parameters, 4) != 0)
 1176                 return -1;
 1177 
 1178         /* Disable interrupts */
 1179         cxm_set_irq_mask(sc, sc->irq_mask | CXM_IRQ_ENC);
 1180 
 1181         sc->encoding = 0;
 1182 
 1183         return 0;
 1184 }
 1185 
 1186 
 1187 static int
 1188 cxm_pause_encoder(struct cxm_softc *sc)
 1189 {
 1190         uint32_t parameter;
 1191 
 1192         /* Pause the encoder */
 1193         parameter = 0;
 1194         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1195                                  CXM_FW_CMD_PAUSE_ENCODER, &parameter, 1) != 0)
 1196                 return -1;
 1197 
 1198         return 0;
 1199 }
 1200 
 1201 
 1202 static int
 1203 cxm_unpause_encoder(struct cxm_softc *sc)
 1204 {
 1205         uint32_t parameter;
 1206 
 1207         /* Unpause the encoder */
 1208         parameter = 1;
 1209         if (cxm_firmware_command(sc, cxm_enc_mailbox,
 1210                                  CXM_FW_CMD_PAUSE_ENCODER, &parameter, 1) != 0)
 1211                 return -1;
 1212 
 1213         return 0;
 1214 }
 1215 
 1216 
 1217 static unsigned int
 1218 cxm_encoder_fixup_byte_order(struct cxm_softc *sc,
 1219                               unsigned int current, size_t offset)
 1220 {
 1221         unsigned int    strips;
 1222         unsigned int    i;
 1223         unsigned int    j;
 1224         unsigned int    k;
 1225         unsigned int    macroblocks_per_line;
 1226         unsigned int    scratch;
 1227         unsigned int    words_per_line;
 1228         uint32_t        *ptr;
 1229         uint32_t        *src;
 1230         size_t          nbytes;
 1231 
 1232         switch (sc->enc_pool.bufs[current].byte_order) {
 1233         case cxm_device_mpeg_byte_order:
 1234 
 1235                 /*
 1236                  * Convert each 32 bit word to the proper byte ordering.
 1237                  */
 1238 
 1239                 for (nbytes = 0,
 1240                      ptr = (uint32_t *)sc->enc_pool.bufs[current].vaddr;
 1241                      nbytes != sc->enc_pool.bufs[current].size;
 1242                      nbytes += sizeof(*ptr), ptr++)
 1243                         *ptr = bswap32(*ptr);
 1244                 break;
 1245 
 1246         case cxm_device_yuv12_byte_order:
 1247 
 1248                 /*
 1249                  * Convert each macro block to planar using
 1250                  * a scratch buffer (the buffer prior to the
 1251                  * current buffer is always free since it marks
 1252                  * the end of the ring buffer).
 1253                  */
 1254 
 1255                 scratch = (current + (CXM_SG_BUFFERS - 1)) % CXM_SG_BUFFERS;
 1256 
 1257                 if (offset) {
 1258                         current = scratch;
 1259                         break;
 1260                 }
 1261 
 1262                 src = (uint32_t *)sc->enc_pool.bufs[current].vaddr;
 1263                 words_per_line = sc->profile->width / sizeof(*ptr);
 1264                 macroblocks_per_line
 1265                   = sc->profile->width / CXM_MACROBLOCK_WIDTH;
 1266                 strips = sc->enc_pool.bufs[current].size
 1267                            / (macroblocks_per_line * CXM_MACROBLOCK_SIZE);
 1268 
 1269                 for (i = 0; i < strips; i++) {
 1270                         ptr = (uint32_t *)sc->enc_pool.bufs[scratch].vaddr
 1271                               + i * macroblocks_per_line * CXM_MACROBLOCK_SIZE
 1272                                 / sizeof(*ptr);
 1273                         for (j = 0; j < macroblocks_per_line; j++) {
 1274                                 for (k = 0; k < CXM_MACROBLOCK_HEIGHT; k++) {
 1275 #if CXM_MACROBLOCK_WIDTH != 16
 1276 #  error CXM_MACROBLOCK_WIDTH != 16
 1277 #endif
 1278                                         *(ptr + k * words_per_line)
 1279                                           = *src++;
 1280                                         *(ptr + k * words_per_line + 1)
 1281                                           = *src++;
 1282                                         *(ptr + k * words_per_line + 2)
 1283                                           = *src++;
 1284                                         *(ptr + k * words_per_line + 3)
 1285                                           = *src++;
 1286                                 }
 1287                                 ptr += CXM_MACROBLOCK_WIDTH / sizeof(*ptr);
 1288                         }
 1289                 }
 1290 
 1291                 sc->enc_pool.bufs[scratch].size
 1292                   = sc->enc_pool.bufs[current].size;
 1293 
 1294                 current = scratch;
 1295                 break;
 1296 
 1297         default:
 1298                 break;
 1299         }
 1300 
 1301         sc->enc_pool.bufs[current].byte_order = cxm_host_byte_order;
 1302 
 1303         return current;
 1304 }
 1305 
 1306 
 1307 static void
 1308 cxm_encoder_dma_discard(struct cxm_softc *sc)
 1309 {
 1310         uint32_t parameters[3];
 1311 
 1312         /* Discard the DMA request */
 1313         parameters[0] = 0;
 1314         parameters[1] = 0;
 1315         parameters[2] = 0;
 1316         if (cxm_queue_firmware_command(sc, cxm_enc_mailbox,
 1317                                        CXM_FW_CMD_SCHED_DMA_TO_HOST,
 1318                                        parameters, 3) == -1) {
 1319                 device_printf(sc->dev,
 1320                     "failed to discard encoder dma request\n");
 1321                 return;
 1322         }
 1323 
 1324         sc->encoding_dma = -1;
 1325 }
 1326 
 1327 
 1328 static void
 1329 cxm_encoder_dma_done(struct cxm_softc *sc)
 1330 {
 1331         int buffers_pending;
 1332         uint32_t status;
 1333 
 1334         if (!sc->encoding_dma) {
 1335                 device_printf(sc->dev,
 1336                     "encoder dma not already in progress\n");
 1337                 return;
 1338         }
 1339 
 1340         buffers_pending = sc->encoding_dma;
 1341         sc->encoding_dma = 0;
 1342 
 1343         if (buffers_pending < 0)
 1344                 return;
 1345 
 1346         status = CSR_READ_4(sc, CXM_REG_DMA_STATUS) & 0x0000000f;
 1347 
 1348         if ((status
 1349              & (CXM_DMA_ERROR_LIST | CXM_DMA_ERROR_WRITE | CXM_DMA_SUCCESS))
 1350             != CXM_DMA_SUCCESS) {
 1351                 device_printf(sc->dev, "encoder dma status %#x\n",
 1352                     (unsigned int)status);
 1353                 return;
 1354         }
 1355 
 1356         /* Update the books */
 1357         crit_enter();
 1358         sc->enc_pool.write = (sc->enc_pool.write + buffers_pending)
 1359                                    % CXM_SG_BUFFERS;
 1360         crit_exit();
 1361 
 1362         /* signal anyone requesting notification */
 1363         if (sc->enc_proc)
 1364                 ksignal (sc->enc_proc, sc->enc_signal);
 1365 
 1366         /* wakeup anyone waiting for data */
 1367         wakeup(&sc->enc_pool.read);
 1368 
 1369         /* wakeup anyone polling for data */
 1370         KNOTE(&sc->enc_kq.ki_note, 0);
 1371 }
 1372 
 1373 
 1374 static void
 1375 cxm_encoder_dma_request(struct cxm_softc *sc)
 1376 {
 1377         enum cxm_byte_order byte_order;
 1378         int buffers_free;
 1379         int buffers_pending;
 1380         unsigned int current;
 1381         unsigned int i;
 1382         unsigned int mailbox;
 1383         unsigned int macroblocks_per_line;
 1384         unsigned int nrequests;
 1385         unsigned int strips;
 1386         uint32_t parameters[CXM_MBX_MAX_PARAMETERS];
 1387         uint32_t type;
 1388         size_t max_sg_segment;
 1389         struct {
 1390                 size_t offset;
 1391                 size_t size;
 1392         } requests[2];
 1393 
 1394         if (sc->encoding_dma) {
 1395                 device_printf(sc->dev, "encoder dma already in progress\n");
 1396                 cxm_encoder_dma_discard(sc);
 1397                 return;
 1398         }
 1399 
 1400         mailbox = sc->enc_mbx
 1401                   + CXM_MBX_FW_DMA_MAILBOX * sizeof(struct cxm_mailbox);
 1402 
 1403         for (i = 0; i < CXM_MBX_MAX_PARAMETERS; i++)
 1404                 parameters[i]
 1405                   = CSR_READ_4(sc,
 1406                                mailbox
 1407                                + offsetof(struct cxm_mailbox, parameters)
 1408                                + i * sizeof(uint32_t)
 1409                               );
 1410 
 1411         byte_order = cxm_device_mpeg_byte_order;
 1412         max_sg_segment = CXM_SG_SEGMENT;
 1413         nrequests = 0;
 1414         type = parameters[0];
 1415 
 1416         switch (type) {
 1417         case 0: /* MPEG */
 1418                 requests[nrequests].offset = parameters[1];
 1419                 requests[nrequests++].size = parameters[2];
 1420                 break;
 1421 
 1422         case 1: /* YUV */
 1423                 byte_order = cxm_device_yuv12_byte_order;
 1424 
 1425                 /*
 1426                  * Simplify macroblock unpacking by ensuring
 1427                  * that strips don't span buffers.
 1428                  */
 1429 
 1430 #if CXM_MACROBLOCK_SIZE % 256
 1431 #  error CXM_MACROBLOCK_SIZE not a multiple of 256
 1432 #endif
 1433 
 1434                 macroblocks_per_line = sc->profile->width
 1435                                        / CXM_MACROBLOCK_WIDTH;
 1436                 strips = CXM_SG_SEGMENT
 1437                          / (macroblocks_per_line * CXM_MACROBLOCK_SIZE);
 1438                 max_sg_segment = strips
 1439                                  * macroblocks_per_line * CXM_MACROBLOCK_SIZE;
 1440 
 1441                 requests[nrequests].offset = parameters[1]; /* Y */
 1442                 requests[nrequests++].size = parameters[2];
 1443                 requests[nrequests].offset = parameters[3]; /* UV */
 1444                 requests[nrequests++].size = parameters[4];
 1445                 break;
 1446 
 1447         case 2: /* PCM (audio) */
 1448         case 3: /* VBI */
 1449         default:
 1450                 device_printf(sc->dev, "encoder dma type %#x unsupported\n",
 1451                     (unsigned int)type);
 1452                 cxm_encoder_dma_discard(sc);
 1453                 return;
 1454         }
 1455 
 1456         /*
 1457          * Determine the number of buffers free at this * instant *
 1458          * taking into consideration that the ring buffer wraps.
 1459          */
 1460         crit_enter();
 1461         buffers_free = sc->enc_pool.read - sc->enc_pool.write;
 1462         if (buffers_free <= 0)
 1463                 buffers_free += CXM_SG_BUFFERS;
 1464         crit_exit();
 1465 
 1466         /*
 1467          * Build the scatter / gather list taking in
 1468          * consideration that the ring buffer wraps,
 1469          * at least one free buffer must always be
 1470          * present to mark the end of the ring buffer,
 1471          * and each transfer must be a multiple of 256.
 1472          */
 1473 
 1474         buffers_pending = 0;
 1475         current = sc->enc_pool.write;
 1476 
 1477         for (i = 0; i < nrequests; i++) {
 1478                 if (!requests[i].size) {
 1479                         device_printf(sc->dev, "encoder dma size is zero\n");
 1480                         cxm_encoder_dma_discard(sc);
 1481                         return;
 1482                 }
 1483 
 1484                 while (requests[i].size) {
 1485                         sc->enc_pool.bufs[current].size
 1486                           = requests[i].size > max_sg_segment
 1487                             ? max_sg_segment : requests[i].size;
 1488                         sc->enc_pool.bufs[current].byte_order = byte_order;
 1489 
 1490                         sc->enc_sg.vaddr[buffers_pending].src
 1491                           = requests[i].offset;
 1492                         sc->enc_sg.vaddr[buffers_pending].dst
 1493                           = sc->enc_pool.bufs[current].baddr;
 1494                         sc->enc_sg.vaddr[buffers_pending].size
 1495                           = (sc->enc_pool.bufs[current].size + 0x000000ff)
 1496                             & 0xffffff00;
 1497 
 1498                         requests[i].offset += sc->enc_pool.bufs[current].size;
 1499                         requests[i].size -= sc->enc_pool.bufs[current].size;
 1500                         buffers_pending++;
 1501                         current = (current + 1) % CXM_SG_BUFFERS;
 1502 
 1503                         if (buffers_pending >= buffers_free) {
 1504                                 device_printf(sc->dev,
 1505                                     "encoder dma not enough buffer space free\n");
 1506                                 cxm_encoder_dma_discard(sc);
 1507                                 return;
 1508                         }
 1509                 }
 1510         }
 1511 
 1512         /* Mark the last transfer in the list */
 1513         sc->enc_sg.vaddr[buffers_pending - 1].size |= 0x80000000;
 1514 
 1515         /* Schedule the DMA */
 1516         parameters[0] = sc->enc_sg.baddr;
 1517         parameters[1] = buffers_pending * sizeof(sc->enc_sg.vaddr[0]);
 1518         parameters[2] = type;
 1519         if (cxm_queue_firmware_command(sc, cxm_enc_mailbox,
 1520                                        CXM_FW_CMD_SCHED_DMA_TO_HOST,
 1521                                        parameters, 3) == -1) {
 1522                 device_printf(sc->dev,
 1523                     "failed to schedule encoder dma request\n");
 1524                 return;
 1525         }
 1526 
 1527         /*
 1528          * Record the number of pending buffers for the
 1529          * benefit of cxm_encoder_dma_done.  Doing this
 1530          * after queuing the command doesn't introduce
 1531          * a race condition since we're already in the
 1532          * interrupt handler.
 1533          */
 1534 
 1535         sc->encoding_dma = buffers_pending;
 1536 }
 1537 
 1538 
 1539 static int
 1540 cxm_encoder_wait_for_lock(struct cxm_softc *sc)
 1541 {
 1542         int muted;
 1543         int locked;
 1544         int result;
 1545 
 1546         locked = 1;
 1547 
 1548         /*
 1549          * Wait for the tuner to lock.
 1550          */
 1551         if (sc->source == cxm_fm_source || sc->source == cxm_tuner_source) {
 1552                 result = cxm_tuner_wait_for_lock(sc);
 1553                 if (result <= 0)
 1554                         return result;
 1555         }
 1556 
 1557         /*
 1558          * Wait for the video decoder to lock.
 1559          */
 1560         if (sc->source != cxm_fm_source) {
 1561                 result = cxm_saa7115_wait_for_lock(sc);
 1562                 if (result < 0)
 1563                         return result;
 1564                 else if (result == 0)
 1565                         locked = 0;
 1566                 }
 1567 
 1568         /*
 1569          * Wait for the audio decoder to lock.
 1570          */
 1571         if (sc->source == cxm_tuner_source) {
 1572                 muted = cxm_msp_is_muted(sc);
 1573 
 1574                 result = cxm_msp_autodetect_standard(sc);
 1575                 if (result < 0)
 1576                         return result;
 1577                 else if (result == 0)
 1578                         locked = 0;
 1579 
 1580                 if (muted == 0 && cxm_msp_unmute(sc) < 0)
 1581                         return -1;
 1582         }
 1583 
 1584         return locked;
 1585 }
 1586 
 1587 
 1588 static void
 1589 cxm_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1590 {
 1591         bus_addr_t *busaddrp;
 1592 
 1593         /*
 1594          * Only the first bus space address is needed
 1595          * since it's known that the memory is physically
 1596          * contiguous due to bus_dmamem_alloc.
 1597          */
 1598 
 1599         busaddrp = (bus_addr_t *)arg;
 1600         *busaddrp = segs->ds_addr;
 1601 }
 1602 
 1603 
 1604 /*
 1605  * the boot time probe routine.
 1606  */
 1607 static int
 1608 cxm_probe(device_t dev)
 1609 {
 1610         struct cxm_dev          *t;
 1611 
 1612         t = cxm_devs;
 1613 
 1614         while(t->name != NULL) {
 1615                 if ((pci_get_vendor(dev) == t->vid) &&
 1616                     (pci_get_device(dev) == t->did)) {
 1617                         device_set_desc(dev, t->name);
 1618                         return 0;
 1619                 }
 1620                 t++;
 1621         }
 1622 
 1623         return ENXIO;
 1624 }
 1625 
 1626 
 1627 /*
 1628  * the attach routine.
 1629  */
 1630 static int
 1631 cxm_attach(device_t dev)
 1632 {
 1633         int             error;
 1634         int             rid;
 1635         int             unit;
 1636         unsigned int    i;
 1637         uint32_t        command;
 1638         struct cxm_softc *sc;
 1639 
 1640         /* Get the device data */
 1641         sc = device_get_softc(dev);
 1642         unit = device_get_unit(dev);
 1643 
 1644         sc->dev = dev;
 1645         sc->type = cxm_iTVC15_type;
 1646 
 1647         switch(pci_get_device(dev)) {
 1648         case PCI_PRODUCT_ICOMPRESSION_ITVC16:
 1649                 sc->type = cxm_iTVC16_type;
 1650                 break;
 1651 
 1652         default:
 1653                 break;
 1654         }
 1655 
 1656         /*
 1657          * Enable bus mastering and memory mapped I/O.
 1658          */
 1659         pci_enable_busmaster(dev);
 1660         pci_enable_io(dev, SYS_RES_MEMORY);
 1661         command = pci_read_config(dev, PCIR_COMMAND, 4);
 1662 
 1663         if (!(command & PCIM_CMD_MEMEN)) {
 1664                 device_printf(dev, "failed to enable memory mappings\n");
 1665                 error = ENXIO;
 1666                 goto fail;
 1667         }
 1668 
 1669         /*
 1670          * Map control/status registers.
 1671          */
 1672         rid = CXM_RID;
 1673         sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
 1674                                         0, ~0, 1, RF_ACTIVE);
 1675 
 1676         if (!sc->mem_res) {
 1677                 device_printf(dev, "could not map memory\n");
 1678                 error = ENXIO;
 1679                 goto fail;
 1680         }
 1681 
 1682         sc->btag = rman_get_bustag(sc->mem_res);
 1683         sc->bhandle = rman_get_bushandle(sc->mem_res);
 1684 
 1685         /*
 1686          * Attach the I2C bus.
 1687          */
 1688         sc->cxm_iic = device_add_child(dev, "cxm_iic", unit);
 1689 
 1690         if (!sc->cxm_iic) {
 1691                 device_printf(dev, "could not add cxm_iic\n");
 1692                 error = ENXIO;
 1693                 goto fail;
 1694         }
 1695 
 1696         error = device_probe_and_attach(sc->cxm_iic);
 1697 
 1698         if (error) {
 1699                 device_printf(dev, "could not attach cxm_iic\n");
 1700                 goto fail;
 1701         }
 1702 
 1703         /*
 1704          * Initialize the tuner.
 1705          */
 1706         if (cxm_tuner_init(sc) < 0) {
 1707                 device_printf(dev, "could not initialize tuner\n");
 1708                 error = ENXIO;
 1709                 goto fail;
 1710         }
 1711 
 1712         /*
 1713          * Initialize the SAA7115.
 1714          */
 1715         if (cxm_saa7115_init(sc) < 0) {
 1716                 device_printf(dev, "could not initialize video decoder\n");
 1717                 error = ENXIO;
 1718                 goto fail;
 1719         }
 1720 
 1721         /*
 1722          * Initialize the MSP3400.
 1723          */
 1724         if (cxm_msp_init(sc) < 0) {
 1725                 device_printf(dev, "could not initialize audio decoder\n");
 1726                 error = ENXIO;
 1727                 goto fail;
 1728         }
 1729 
 1730         /*
 1731          * Initialize the IR Remote.
 1732          */
 1733         if (cxm_ir_init(sc) < 0) {
 1734                 device_printf(dev, "could not initialize IR remote\n");
 1735                 error = ENXIO;
 1736                 goto fail;
 1737         }
 1738 
 1739         sc->dec_mbx = -1;
 1740         sc->enc_mbx = -1;
 1741 
 1742         /*
 1743          * Disable the Conexant device.
 1744          *
 1745          * This is done * after * attaching the I2C bus so
 1746          * cxm_stop_hardware can mute the video and audio
 1747          * decoders.
 1748          */
 1749         cxm_stop_hardware(sc);
 1750 
 1751         /*
 1752          * Allocate our interrupt.
 1753          */
 1754         rid = 0;
 1755         sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
 1756                                 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
 1757 
 1758         if (sc->irq_res == NULL) {
 1759                 device_printf(dev, "could not map interrupt\n");
 1760                 error = ENXIO;
 1761                 goto fail;
 1762         }
 1763 
 1764         error = bus_setup_intr(dev, sc->irq_res, 0,
 1765                                cxm_intr, sc, &sc->ih_cookie, NULL);
 1766         if (error) {
 1767                 device_printf(dev, "could not setup irq\n");
 1768                 goto fail;
 1769 
 1770         }
 1771 
 1772         /*
 1773          * Allocate a DMA tag for the parent bus.
 1774          */
 1775         error = bus_dma_tag_create(NULL, 1, 0,
 1776                                    BUS_SPACE_MAXADDR_32BIT,
 1777                                    BUS_SPACE_MAXADDR, NULL, NULL,
 1778                                    BUS_SPACE_MAXSIZE_32BIT, 1,
 1779                                    BUS_SPACE_MAXSIZE_32BIT, 0,
 1780                                    &sc->parent_dmat);
 1781         if (error) {
 1782                 device_printf(dev, "could not create parent bus DMA tag\n");
 1783                 goto fail;
 1784         }
 1785 
 1786         /*
 1787          * Allocate a DMA tag for the encoder buffers.
 1788          */
 1789         error = bus_dma_tag_create(sc->parent_dmat, 256, 0,
 1790                                    BUS_SPACE_MAXADDR_32BIT,
 1791                                    BUS_SPACE_MAXADDR, NULL, NULL,
 1792                                    CXM_SG_SEGMENT, 1,
 1793                                    BUS_SPACE_MAXSIZE_32BIT, 0,
 1794                                    &sc->enc_pool.dmat);
 1795         if (error) {
 1796                 device_printf(dev,
 1797                               "could not create encoder buffer DMA tag\n");
 1798                 goto fail;
 1799         }
 1800 
 1801         for (i = 0; i < CXM_SG_BUFFERS; i++) {
 1802 
 1803                 /*
 1804                  * Allocate the encoder buffer.
 1805                  */
 1806                 error = bus_dmamem_alloc(sc->enc_pool.dmat,
 1807                                          (void **)&sc->enc_pool.bufs[i].vaddr,
 1808                                          BUS_DMA_NOWAIT,
 1809                                          &sc->enc_pool.bufs[i].dmamap);
 1810                 if (error) {
 1811                         device_printf(dev,
 1812                                       "could not allocate encoder buffer\n");
 1813                         goto fail;
 1814                 }
 1815 
 1816                 /*
 1817                  * Map the encoder buffer.
 1818                  */
 1819                 error = bus_dmamap_load(sc->enc_pool.dmat,
 1820                                         sc->enc_pool.bufs[i].dmamap,
 1821                                         sc->enc_pool.bufs[i].vaddr,
 1822                                         CXM_SG_SEGMENT,
 1823                                         cxm_mapmem,
 1824                                         &sc->enc_pool.bufs[i].baddr, 0);
 1825                 if (error) {
 1826                         device_printf(dev, "could not map encoder buffer\n");
 1827                         goto fail;
 1828                 }
 1829         }
 1830 
 1831         /*
 1832          * Allocate a DMA tag for the scatter / gather list.
 1833          */
 1834         error = bus_dma_tag_create(sc->parent_dmat, 1, 0,
 1835                                    BUS_SPACE_MAXADDR_32BIT,
 1836                                    BUS_SPACE_MAXADDR, NULL, NULL,
 1837                                    CXM_SG_BUFFERS
 1838                                    * sizeof(struct cxm_sg_entry), 1,
 1839                                    BUS_SPACE_MAXSIZE_32BIT, 0,
 1840                                    &sc->enc_sg.dmat);
 1841         if (error) {
 1842                 device_printf(dev,
 1843                               "could not create scatter / gather DMA tag\n");
 1844                 goto fail;
 1845         }
 1846 
 1847         /*
 1848          * Allocate the scatter / gather list.
 1849          */
 1850         error = bus_dmamem_alloc(sc->enc_sg.dmat, (void **)&sc->enc_sg.vaddr,
 1851                                  BUS_DMA_NOWAIT, &sc->enc_sg.dmamap);
 1852         if (error) {
 1853                 device_printf(dev,
 1854                               "could not allocate scatter / gather list\n");
 1855                 goto fail;
 1856         }
 1857 
 1858         /*
 1859          * Map the scatter / gather list.
 1860          */
 1861         error = bus_dmamap_load(sc->enc_sg.dmat, sc->enc_sg.dmamap,
 1862                                 sc->enc_sg.vaddr,
 1863                                 CXM_SG_BUFFERS * sizeof(struct cxm_sg_entry),
 1864                                 cxm_mapmem, &sc->enc_sg.baddr, 0);
 1865         if (error) {
 1866                 device_printf(dev, "could not map scatter / gather list\n");
 1867                 goto fail;
 1868         }
 1869 
 1870         /*
 1871          * Initialize the hardware.
 1872          */
 1873         if (cxm_init_hardware(sc) < 0) {
 1874                 device_printf(dev, "could not initialize hardware\n");
 1875                 error = ENXIO;
 1876                 goto fail;
 1877         }
 1878 
 1879         sc->profile = &dvd_full_d1_ntsc_profile;
 1880 
 1881         sc->source = cxm_tuner_source;
 1882 
 1883 
 1884         /* make the device entries */
 1885         sc->cxm_dev_t = make_dev(&cxm_ops, unit,
 1886                                  0, 0, 0444, "cxm%d",  unit);
 1887 
 1888         return 0;
 1889 
 1890 fail:
 1891         if (sc->enc_sg.baddr)
 1892                 bus_dmamap_unload(sc->enc_sg.dmat, sc->enc_sg.dmamap);
 1893         if (sc->enc_sg.vaddr)
 1894                 bus_dmamem_free(sc->enc_sg.dmat, sc->enc_sg.vaddr,
 1895                                 sc->enc_sg.dmamap);
 1896         if (sc->enc_sg.dmat)
 1897                 bus_dma_tag_destroy(sc->enc_sg.dmat);
 1898 
 1899         for (i = 0; i < CXM_SG_BUFFERS; i++) {
 1900                 if (sc->enc_pool.bufs[i].baddr)
 1901                         bus_dmamap_unload(sc->enc_pool.dmat,
 1902                                           sc->enc_pool.bufs[i].dmamap);
 1903                 if (sc->enc_pool.bufs[i].vaddr)
 1904                         bus_dmamem_free(sc->enc_pool.dmat,
 1905                                         sc->enc_pool.bufs[i].vaddr,
 1906                                         sc->enc_pool.bufs[i].dmamap);
 1907         }
 1908 
 1909         if (sc->enc_pool.dmat)
 1910                 bus_dma_tag_destroy(sc->enc_pool.dmat);
 1911 
 1912         if (sc->parent_dmat)
 1913                 bus_dma_tag_destroy(sc->parent_dmat);
 1914 
 1915         /*
 1916          * Detach the I2C bus.
 1917          *
 1918          * This is done * after * deallocating the scatter / gather
 1919          * list and buffers so the kernel has a better chance of
 1920          * gracefully handling a memory shortage.
 1921          *
 1922          * Detach the children before recursively deleting
 1923          * in case a child has a pointer to a grandchild
 1924          * which is used by the child's detach routine.
 1925          */
 1926         bus_generic_detach(dev);
 1927         if (sc->cxm_iic)
 1928                 device_delete_child(dev, sc->cxm_iic);
 1929 
 1930         if (sc->ih_cookie)
 1931                 bus_teardown_intr(dev, sc->irq_res, sc->ih_cookie);
 1932         if (sc->irq_res)
 1933                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
 1934         if (sc->mem_res)
 1935                 bus_release_resource(dev, SYS_RES_MEMORY, CXM_RID, sc->mem_res);
 1936 
 1937         return error;
 1938 }
 1939 
 1940 /*
 1941  * the detach routine.
 1942  */
 1943 static int
 1944 cxm_detach(device_t dev)
 1945 {
 1946         unsigned int i;
 1947         struct cxm_softc *sc;
 1948         device_t child;
 1949 
 1950         /* Get the device data */
 1951         sc = device_get_softc(dev);
 1952 
 1953         /* Disable the Conexant device. */
 1954         cxm_stop_hardware(sc);
 1955 
 1956         /* Unregister the /dev/cxmN device. */
 1957         dev_ops_remove_minor(&cxm_ops, /*0, */device_get_unit(dev));
 1958 
 1959         /*
 1960          * Deallocate scatter / gather list and buffers.
 1961          */
 1962         bus_dmamap_unload(sc->enc_sg.dmat, sc->enc_sg.dmamap);
 1963         bus_dmamem_free(sc->enc_sg.dmat, sc->enc_sg.vaddr, sc->enc_sg.dmamap);
 1964 
 1965         bus_dma_tag_destroy(sc->enc_sg.dmat);
 1966 
 1967         for (i = 0; i < CXM_SG_BUFFERS; i++) {
 1968                 bus_dmamap_unload(sc->enc_pool.dmat,
 1969                                   sc->enc_pool.bufs[i].dmamap);
 1970                 bus_dmamem_free(sc->enc_pool.dmat, sc->enc_pool.bufs[i].vaddr,
 1971                                 sc->enc_pool.bufs[i].dmamap);
 1972         }
 1973 
 1974         bus_dma_tag_destroy(sc->enc_pool.dmat);
 1975 
 1976         bus_dma_tag_destroy(sc->parent_dmat);
 1977 
 1978         /*
 1979          * Detach the I2C bus.
 1980          *
 1981          * This is done * after * deallocating the scatter / gather
 1982          * list and buffers so the kernel has a better chance of
 1983          * gracefully handling a memory shortage.
 1984          *
 1985          * Detach the children before recursively deleting
 1986          * in case a child has a pointer to a grandchild
 1987          * which is used by the child's detach routine.
 1988          *
 1989          * Remember the child before detaching so we can
 1990          * delete it (bus_generic_detach indirectly zeroes
 1991          * sc->child_dev).
 1992          */
 1993         child = sc->cxm_iic;
 1994         bus_generic_detach(dev);
 1995         if (child)
 1996                 device_delete_child(dev, child);
 1997 
 1998         /* Deallocate resources. */
 1999         bus_teardown_intr(dev, sc->irq_res, sc->ih_cookie);
 2000         bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
 2001         bus_release_resource(dev, SYS_RES_MEMORY, CXM_RID, sc->mem_res);
 2002 
 2003         return 0;
 2004 }
 2005 
 2006 /*
 2007  * the shutdown routine.
 2008  */
 2009 static int
 2010 cxm_shutdown(device_t dev)
 2011 {
 2012         struct cxm_softc *sc = device_get_softc(dev);
 2013 
 2014         /* Disable the Conexant device. */
 2015         cxm_stop_hardware(sc);
 2016 
 2017         return 0;
 2018 }
 2019 
 2020 /*
 2021  * the interrupt routine.
 2022  */
 2023 static void
 2024 cxm_intr(void *arg)
 2025 {
 2026         uint32_t status;
 2027         struct cxm_softc *sc;
 2028 
 2029         /* Get the device data */
 2030         sc = (struct cxm_softc *)arg;
 2031 
 2032         status = CSR_READ_4(sc, CXM_REG_IRQ_STATUS);
 2033 
 2034         status &= ~sc->irq_mask;
 2035 
 2036         if (!status)
 2037                 return;
 2038 
 2039         /* Process DMA done before handling a new DMA request or EOS */
 2040         if (status & CXM_IRQ_ENC_DMA_DONE)
 2041                 cxm_encoder_dma_done(sc);
 2042 
 2043         if (status & CXM_IRQ_ENC_DMA_REQUEST)
 2044                 cxm_encoder_dma_request(sc);
 2045 
 2046         if (status & CXM_IRQ_ENC_EOS) {
 2047                 sc->encoding_eos = 1;
 2048                 wakeup(&sc->encoding_eos);
 2049         }
 2050 
 2051         cxm_set_irq_status(sc, status);
 2052 }
 2053 
 2054 
 2055 /*
 2056  * the child detached routine.
 2057  */
 2058 static void
 2059 cxm_child_detached(device_t dev, device_t child)
 2060 {
 2061         struct cxm_softc *sc;
 2062 
 2063         /* Get the device data */
 2064         sc = device_get_softc(dev);
 2065 
 2066         if (child == sc->cxm_iic)
 2067                 sc->cxm_iic = NULL;
 2068 }
 2069 
 2070 
 2071 static int
 2072 cxm_read_ivar(device_t dev, device_t child, int index, uintptr_t* val)
 2073 {
 2074         struct cxm_softc *sc;
 2075 
 2076         /* Get the device data */
 2077         sc = device_get_softc(dev);
 2078 
 2079         switch (index) {
 2080         case CXM_IVAR_BHANDLE:
 2081                 *(bus_space_handle_t **)val = &sc->bhandle;
 2082                 break;
 2083 
 2084         case CXM_IVAR_BTAG:
 2085                 *(bus_space_tag_t **)val = &sc->btag;
 2086                 break;
 2087 
 2088         case CXM_IVAR_IICBUS:
 2089                 *(device_t **)val = &sc->iicbus;
 2090                 break;
 2091 
 2092         default:
 2093                 return ENOENT;
 2094         }
 2095 
 2096         return 0;
 2097 }
 2098 
 2099 
 2100 static int
 2101 cxm_write_ivar(device_t dev, device_t child, int index, uintptr_t val)
 2102 {
 2103         struct cxm_softc *sc;
 2104 
 2105         /* Get the device data */
 2106         sc = device_get_softc(dev);
 2107 
 2108         switch (index) {
 2109         case CXM_IVAR_BHANDLE:
 2110                 return EINVAL;
 2111 
 2112         case CXM_IVAR_BTAG:
 2113                 return EINVAL;
 2114 
 2115         case CXM_IVAR_IICBUS:
 2116                 if (sc->iicbus)
 2117                         return EINVAL;
 2118                 sc->iicbus = val ? *(device_t *)val : NULL;
 2119                 break;
 2120 
 2121         default:
 2122                 return ENOENT;
 2123         }
 2124 
 2125         return 0;
 2126 }
 2127 
 2128 
 2129 /*---------------------------------------------------------
 2130 **
 2131 **      Conexant iTVC15 / iTVC16 character device driver routines
 2132 **
 2133 **---------------------------------------------------------
 2134 */
 2135 
 2136 #define UNIT(x)         ((x) & 0x0f)
 2137 #define FUNCTION(x)     (x >> 4)
 2138 
 2139 /*
 2140  *
 2141  */
 2142 int
 2143 cxm_open(struct dev_open_args *ap)
 2144 {
 2145         cdev_t          dev = ap->a_head.a_dev;
 2146         int             unit;
 2147         struct cxm_softc *sc;
 2148 
 2149         unit = UNIT(minor(dev));
 2150 
 2151         /* Get the device data */
 2152         sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
 2153         if (sc == NULL) {
 2154                 /* the device is no longer valid/functioning */
 2155                 return ENXIO;
 2156         }
 2157 
 2158         if (sc->is_opened)
 2159                 return EBUSY;
 2160 
 2161         sc->is_opened = 1;
 2162         sc->mpeg = 1;
 2163 
 2164         /* Record that the device is now busy */
 2165         device_busy(devclass_get_device(cxm_devclass, unit));
 2166 
 2167         return 0;
 2168 }
 2169 
 2170 
 2171 /*
 2172  *
 2173  */
 2174 int
 2175 cxm_close(struct dev_close_args *ap)
 2176 {
 2177         cdev_t          dev = ap->a_head.a_dev;
 2178         int             unit;
 2179         struct cxm_softc *sc;
 2180 
 2181         unit = UNIT(minor(dev));
 2182 
 2183         /* Get the device data */
 2184         sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
 2185         if (sc == NULL) {
 2186                 /* the device is no longer valid/functioning */
 2187                 return ENXIO;
 2188         }
 2189 
 2190         if (cxm_stop_encoder(sc) < 0)
 2191                 return ENXIO;
 2192 
 2193         sc->enc_pool.offset = 0;
 2194         sc->enc_pool.read = 0;
 2195         sc->enc_pool.write = 0;
 2196 
 2197         sc->enc_proc = NULL;
 2198         sc->enc_signal = 0;
 2199 
 2200         device_unbusy(devclass_get_device(cxm_devclass, unit));
 2201 
 2202         sc->is_opened = 0;
 2203 
 2204         return 0;
 2205 }
 2206 
 2207 
 2208 /*
 2209  *
 2210  */
 2211 int
 2212 cxm_read(struct dev_read_args *ap)
 2213 {
 2214         cdev_t          dev = ap->a_head.a_dev;
 2215         int             buffers_available;
 2216         int             buffers_read;
 2217         int             error;
 2218         int             unit;
 2219         unsigned int    current;
 2220         unsigned int    i;
 2221         size_t          nbytes;
 2222         size_t          offset;
 2223         struct cxm_softc *sc;
 2224 
 2225         unit = UNIT(minor(dev));
 2226 
 2227         /* Get the device data */
 2228         sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
 2229         if (sc == NULL) {
 2230                 /* the device is no longer valid/functioning */
 2231                 return ENXIO;
 2232         }
 2233 
 2234         /* Only trigger the encoder if the ring buffer is empty */
 2235         if (!sc->encoding && sc->enc_pool.read == sc->enc_pool.write) {
 2236                 if (cxm_start_encoder(sc) < 0)
 2237                         return ENXIO;
 2238                 if (ap->a_ioflag & IO_NDELAY)
 2239                         return EWOULDBLOCK;
 2240         }
 2241 
 2242         buffers_available = 0;
 2243 
 2244         crit_enter();
 2245         while (sc->enc_pool.read == sc->enc_pool.write) {
 2246                 error = tsleep(&sc->enc_pool.read, PCATCH, "cxmrd", 0);
 2247                 if (error) {
 2248                         crit_exit();
 2249                         return error;
 2250                 }
 2251         }
 2252 
 2253         /*
 2254          * Determine the number of buffers available at this * instant *
 2255          * taking in consideration that the ring buffer wraps.
 2256          */
 2257         buffers_available = sc->enc_pool.write - sc->enc_pool.read;
 2258         if (buffers_available < 0)
 2259                 buffers_available += CXM_SG_BUFFERS;
 2260         crit_exit();
 2261 
 2262         offset = sc->enc_pool.offset;
 2263 
 2264         for (buffers_read = 0, i = sc->enc_pool.read;
 2265              buffers_read != buffers_available && ap->a_uio->uio_resid;
 2266              buffers_read++, i = (i + 1) % CXM_SG_BUFFERS) {
 2267 
 2268                 current = cxm_encoder_fixup_byte_order (sc, i, offset);
 2269 
 2270                 nbytes = sc->enc_pool.bufs[current].size - offset;
 2271 
 2272                 /* Don't transfer more than requested */
 2273                 if (nbytes > ap->a_uio->uio_resid)
 2274                         nbytes = ap->a_uio->uio_resid;
 2275 
 2276                 error = uiomove(sc->enc_pool.bufs[current].vaddr + offset,
 2277                                 nbytes, ap->a_uio);
 2278                 if (error)
 2279                         return error;
 2280 
 2281                 offset += nbytes;
 2282 
 2283                 /* Handle a partial read of a buffer */
 2284                 if (!ap->a_uio->uio_resid && offset != sc->enc_pool.bufs[i].size)
 2285                         break;
 2286 
 2287                 offset = 0;
 2288         }
 2289 
 2290         sc->enc_pool.offset = offset;
 2291 
 2292         /* Update the books */
 2293         crit_enter();
 2294         sc->enc_pool.read = (sc->enc_pool.read + buffers_read)
 2295                             % CXM_SG_BUFFERS;
 2296         crit_exit();
 2297 
 2298         return 0;
 2299 }
 2300 
 2301 
 2302 /*
 2303  *
 2304  */
 2305 int
 2306 cxm_ioctl(struct dev_ioctl_args *ap)
 2307 {
 2308         cdev_t          dev = ap->a_head.a_dev;
 2309         int             brightness;
 2310         int             chroma_saturation;
 2311         int             contrast;
 2312         int             fps;
 2313         int             hue;
 2314         int             result;
 2315         int             status;
 2316         int             unit;
 2317         unsigned int    i;
 2318         unsigned int    sig;
 2319         unsigned long   freq;
 2320         struct cxm_softc *sc;
 2321         enum cxm_source source;
 2322         struct bktr_capture_area *cap;
 2323         struct bktr_remote *remote;
 2324 
 2325         unit = UNIT(minor(dev));
 2326 
 2327         /* Get the device data */
 2328         sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
 2329         if (sc == NULL) {
 2330                 /* the device is no longer valid/functioning */
 2331                 return ENXIO;
 2332         }
 2333 
 2334         switch (ap->a_cmd) {
 2335         case BT848_GAUDIO:
 2336                 switch (cxm_msp_selected_source(sc)) {
 2337                 case cxm_tuner_source:
 2338                         *(int *) ap->a_data = AUDIO_TUNER;
 2339                         break;
 2340 
 2341                 case cxm_line_in_source_composite:
 2342                 case cxm_line_in_source_svideo:
 2343                         *(int *) ap->a_data = AUDIO_EXTERN;
 2344                         break;
 2345 
 2346                 case cxm_fm_source:
 2347                         *(int *) ap->a_data = AUDIO_INTERN;
 2348                         break;
 2349 
 2350                 default:
 2351                         return ENXIO;
 2352                 }
 2353 
 2354                 if (cxm_msp_is_muted(sc) == 1)
 2355                         *(int *) ap->a_data |= AUDIO_MUTE;
 2356                 break;
 2357 
 2358         case BT848_SAUDIO:
 2359                 source = cxm_unknown_source;
 2360 
 2361                 switch (*(int *) ap->a_data) {
 2362                 case AUDIO_TUNER:
 2363                         source = cxm_tuner_source;
 2364                         break;
 2365 
 2366                 case AUDIO_EXTERN:
 2367                         source = cxm_line_in_source_composite;
 2368                         break;
 2369 
 2370                 case AUDIO_INTERN:
 2371                         source = cxm_fm_source;
 2372                         break;
 2373 
 2374                 case AUDIO_MUTE:
 2375                         if (cxm_msp_mute(sc) < 0)
 2376                                 return ENXIO;
 2377                         return 0;
 2378 
 2379                 case AUDIO_UNMUTE:
 2380                         if (cxm_msp_unmute(sc) < 0)
 2381                                 return ENXIO;
 2382                         return 0;
 2383 
 2384                 default:
 2385                         return EINVAL;
 2386                 }
 2387 
 2388                 if (sc->encoding) {
 2389 
 2390                         /*
 2391                          * Switching between audio + video and audio only
 2392                          * subtypes isn't supported while encoding.
 2393                          */
 2394 
 2395                         if (source != sc->source
 2396                             && (source == cxm_fm_source
 2397                                 || sc->source == cxm_fm_source))
 2398                                 return EBUSY;
 2399                 }
 2400 
 2401                 if (cxm_pause_encoder(sc) < 0)
 2402                         return ENXIO;
 2403 
 2404                 if (cxm_msp_select_source(sc, source) < 0)
 2405                         return ENXIO;
 2406 
 2407                 if (source == cxm_fm_source)
 2408                         sc->source = source;
 2409 
 2410                 result = cxm_encoder_wait_for_lock(sc);
 2411                 if (result < 0)
 2412                         return ENXIO;
 2413                 else if (result == 0)
 2414                         return EINVAL;
 2415 
 2416                 if (cxm_unpause_encoder(sc) < 0)
 2417                         return ENXIO;
 2418                 break;
 2419 
 2420         case BT848_GBRIG:
 2421                 brightness = cxm_saa7115_get_brightness(sc);
 2422 
 2423                 if (brightness < 0)
 2424                         return ENXIO;
 2425 
 2426                 /*
 2427                  * Brooktree brightness:
 2428                  * 0x80 = -50.0%, 0x00 = +0.0%, 0x7f = +49.6%
 2429                  */
 2430                 *(int *)ap->a_data = (int)(unsigned char)brightness - 128;
 2431                 break;
 2432 
 2433         case BT848_SBRIG:
 2434 
 2435                 /*
 2436                  * Brooktree brightness:
 2437                  * 0x80 = -50.0%, 0x00 = +0.0%, 0x7f = +49.6%
 2438                  */
 2439                 brightness = *(int *)ap->a_data + 128;
 2440 
 2441                 if (cxm_saa7115_set_brightness(sc, brightness) < 0)
 2442                         return ENXIO;
 2443                 break;
 2444 
 2445         case METEORGBRIG:
 2446                 brightness = cxm_saa7115_get_brightness(sc);
 2447 
 2448                 if (brightness < 0)
 2449                         return ENXIO;
 2450 
 2451                 *(unsigned char *)ap->a_data = (unsigned char)brightness;
 2452                 break;
 2453 
 2454         case METEORSBRIG:
 2455                 brightness = *(unsigned char *)ap->a_data;
 2456 
 2457                 if (cxm_saa7115_set_brightness(sc, brightness) < 0)
 2458                         return ENXIO;
 2459                 break;
 2460 
 2461         case BT848_GCSAT:
 2462                 chroma_saturation = cxm_saa7115_get_chroma_saturation(sc);
 2463 
 2464                 if (chroma_saturation < 0)
 2465                         return ENXIO;
 2466 
 2467                 /*
 2468                  * Brooktree chroma saturation:
 2469                  * 0x000 = 0%, 0x0fe = 100%, 0x1ff = 201.18%
 2470                  */
 2471                 *(int *)ap->a_data = ((signed char)chroma_saturation > 0)
 2472                                 ? (chroma_saturation * 4 - 2) : 0;
 2473                 break;
 2474 
 2475         case BT848_SCSAT:
 2476 
 2477                 /*
 2478                  * Brooktree chroma saturation:
 2479                  * 0x000 = 0%, 0x0fe = 100%, 0x1ff = 201.18%
 2480                  */
 2481                 chroma_saturation = (*(int *)ap->a_data & 0x1ff) < 510
 2482                                       ? ((*(int *)ap->a_data & 0x1ff) + 2) / 4 : 127;
 2483 
 2484                 if (cxm_saa7115_set_chroma_saturation(sc, chroma_saturation)
 2485                     < 0)
 2486                         return ENXIO;
 2487 
 2488                 break;
 2489 
 2490         case METEORGCSAT:
 2491                 chroma_saturation = cxm_saa7115_get_chroma_saturation(sc);
 2492 
 2493                 if (chroma_saturation < 0)
 2494                         return ENXIO;
 2495 
 2496                 *(unsigned char *)ap->a_data = (unsigned char)chroma_saturation;
 2497                 break;
 2498 
 2499         case METEORSCSAT:
 2500                 chroma_saturation = *(unsigned char *)ap->a_data;
 2501 
 2502                 if (cxm_saa7115_set_chroma_saturation(sc, chroma_saturation)
 2503                     < 0)
 2504                         return ENXIO;
 2505                 break;
 2506 
 2507         case METEORGCONT:
 2508                 contrast = cxm_saa7115_get_contrast(sc);
 2509 
 2510                 if (contrast < 0)
 2511                         return ENXIO;
 2512 
 2513                 *(unsigned char *)ap->a_data = (unsigned char)contrast;
 2514                 break;
 2515 
 2516         case METEORSCONT:
 2517                 contrast = *(unsigned char *)ap->a_data;
 2518 
 2519                 if (cxm_saa7115_set_contrast(sc, contrast) < 0)
 2520                         return ENXIO;
 2521                 break;
 2522 
 2523         case BT848_GHUE:
 2524                 hue = cxm_saa7115_get_hue(sc);
 2525 
 2526                 if (hue < 0)
 2527                         return ENXIO;
 2528 
 2529                 *(int *)ap->a_data = (signed char)hue;
 2530                 break;
 2531 
 2532         case BT848_SHUE:
 2533                 hue = *(int *)ap->a_data;
 2534 
 2535                 if (cxm_saa7115_set_hue(sc, hue) < 0)
 2536                         return ENXIO;
 2537                 break;
 2538 
 2539         case METEORGHUE:
 2540                 hue = cxm_saa7115_get_hue(sc);
 2541 
 2542                 if (hue < 0)
 2543                         return ENXIO;
 2544 
 2545                 *(signed char *)ap->a_data = (signed char)hue;
 2546                 break;
 2547 
 2548         case METEORSHUE:
 2549                 hue = *(signed char *)ap->a_data;
 2550 
 2551                 if (cxm_saa7115_set_hue(sc, hue) < 0)
 2552                         return ENXIO;
 2553                 break;
 2554 
 2555         case METEORCAPTUR:
 2556                 switch (*(int *) ap->a_data) {
 2557                 case METEOR_CAP_CONTINOUS:
 2558                         if (cxm_start_encoder(sc) < 0)
 2559                                 return ENXIO;
 2560                         break;
 2561 
 2562                 case METEOR_CAP_STOP_CONT:
 2563                         if (cxm_stop_encoder(sc) < 0)
 2564                                 return ENXIO;
 2565                         break;
 2566 
 2567                 default:
 2568                         return EINVAL;
 2569                 }
 2570                 break;
 2571 
 2572         case BT848_GCAPAREA:
 2573                 cap = (struct bktr_capture_area *)ap->a_data;
 2574                 memset (cap, 0, sizeof (*cap));
 2575                 cap->x_offset = 0;
 2576                 cap->y_offset = 0;
 2577                 cap->x_size = sc->profile->width;
 2578                 cap->y_size = sc->profile->height;
 2579                 break;
 2580 
 2581         case BT848_SCAPAREA:
 2582                 if (sc->encoding)
 2583                         return EBUSY;
 2584 
 2585                 cap = (struct bktr_capture_area *)ap->a_data;
 2586                 if (cap->x_offset || cap->y_offset
 2587                     || (cap->x_size % CXM_MACROBLOCK_WIDTH)
 2588                     || (cap->y_size % CXM_MACROBLOCK_HEIGHT))
 2589                         return EINVAL;
 2590 
 2591                 /*
 2592                  * Setting the width and height has the side effect of
 2593                  * chosing between the VCD, SVCD, and DVD profiles.
 2594                  */
 2595 
 2596                 for (i = 0; i < NUM_ELEMENTS(codec_profiles); i++)
 2597                         if (codec_profiles[i]->width == cap->x_size
 2598                             && codec_profiles[i]->height == cap->y_size)
 2599                                 break;
 2600 
 2601                 if (i >= NUM_ELEMENTS(codec_profiles))
 2602                         return EINVAL;
 2603 
 2604                 sc->profile = codec_profiles[i];
 2605                 break;
 2606 
 2607         case BT848GFMT:
 2608                 switch (cxm_saa7115_detected_format(sc)) {
 2609                 case cxm_ntsc_60hz_source_format:
 2610                         *(unsigned long *)ap->a_data = BT848_IFORM_F_NTSCM;
 2611                         break;
 2612 
 2613                 case cxm_pal_50hz_source_format:
 2614                         *(unsigned long *)ap->a_data = BT848_IFORM_F_PALBDGHI;
 2615                         break;
 2616 
 2617                 case cxm_secam_50hz_source_format:
 2618                         *(unsigned long *)ap->a_data = BT848_IFORM_F_SECAM;
 2619                         break;
 2620 
 2621                 case cxm_pal_60hz_source_format:
 2622                         *(unsigned long *)ap->a_data = BT848_IFORM_F_PALM;
 2623                         break;
 2624 
 2625                 case cxm_bw_50hz_source_format:
 2626                 case cxm_bw_60hz_source_format:
 2627                 case cxm_ntsc_50hz_source_format:
 2628                         *(unsigned long *)ap->a_data = BT848_IFORM_F_AUTO;
 2629                         break;
 2630 
 2631                 default:
 2632                         return ENXIO;
 2633                 }
 2634                 break;
 2635 
 2636         case METEORGFMT:
 2637                 switch (cxm_saa7115_detected_format(sc)) {
 2638                 case cxm_ntsc_60hz_source_format:
 2639                         *(unsigned long *)ap->a_data = METEOR_FMT_NTSC;
 2640                         break;
 2641 
 2642                 case cxm_pal_50hz_source_format:
 2643                         *(unsigned long *)ap->a_data = METEOR_FMT_PAL;
 2644                         break;
 2645 
 2646                 case cxm_secam_50hz_source_format:
 2647                         *(unsigned long *)ap->a_data = METEOR_FMT_SECAM;
 2648                         break;
 2649 
 2650                 case cxm_bw_50hz_source_format:
 2651                 case cxm_bw_60hz_source_format:
 2652                 case cxm_ntsc_50hz_source_format:
 2653                 case cxm_pal_60hz_source_format:
 2654                         *(unsigned long *)ap->a_data = METEOR_FMT_AUTOMODE;
 2655                         break;
 2656 
 2657                 default:
 2658                         return ENXIO;
 2659                 }
 2660                 break;
 2661 
 2662         case METEORGFPS:
 2663                 fps = cxm_saa7115_detected_fps(sc);
 2664 
 2665                 if (fps < 0)
 2666                         return ENXIO;
 2667 
 2668                 *(unsigned short *)ap->a_data = fps;
 2669                 break;
 2670 
 2671         case METEORGINPUT:
 2672                 switch (sc->source) {
 2673                 case cxm_tuner_source:
 2674                         *(unsigned long *)ap->a_data = METEOR_INPUT_DEV1;
 2675                         break;
 2676 
 2677                 case cxm_line_in_source_composite:
 2678                         *(unsigned long *)ap->a_data = METEOR_INPUT_DEV2;
 2679                         break;
 2680 
 2681                 case cxm_line_in_source_svideo:
 2682                         *(unsigned long *)ap->a_data = METEOR_INPUT_DEV_SVIDEO;
 2683                         break;
 2684 
 2685                 default:
 2686                         return ENXIO;
 2687                 }
 2688                 break;
 2689 
 2690         case METEORSINPUT:
 2691                 source = cxm_unknown_source;
 2692 
 2693                 switch (*(unsigned long *)ap->a_data & 0xf000) {
 2694                 case METEOR_INPUT_DEV1:
 2695                         source = cxm_tuner_source;
 2696                         break;
 2697 
 2698                 case METEOR_INPUT_DEV2:
 2699                         source = cxm_line_in_source_composite;
 2700                         break;
 2701 
 2702                 case METEOR_INPUT_DEV_SVIDEO:
 2703                         source = cxm_line_in_source_svideo;
 2704                         break;
 2705 
 2706                 default:
 2707                          return EINVAL;
 2708                 }
 2709 
 2710                 if (sc->encoding) {
 2711 
 2712                         /*
 2713                          * Switching between audio + video and audio only
 2714                          * subtypes isn't supported while encoding.
 2715                          */
 2716 
 2717                         if (source != sc->source
 2718                             && (source == cxm_fm_source
 2719                                 || sc->source == cxm_fm_source))
 2720                                 return EBUSY;
 2721                 }
 2722 
 2723                 if (cxm_pause_encoder(sc) < 0)
 2724                         return ENXIO;
 2725 
 2726                 if (cxm_saa7115_select_source(sc, source) < 0)
 2727                         return ENXIO;
 2728                 if (cxm_msp_select_source(sc, source) < 0)
 2729                         return ENXIO;
 2730                 sc->source = source;
 2731 
 2732                 result = cxm_encoder_wait_for_lock(sc);
 2733                 if (result < 0)
 2734                         return ENXIO;
 2735                 else if (result == 0)
 2736                         return EINVAL;
 2737 
 2738                 if (cxm_unpause_encoder(sc) < 0)
 2739                         return ENXIO;
 2740                 break;
 2741 
 2742         case METEORGSIGNAL:
 2743                 *(unsigned int *)ap->a_data = sc->enc_signal;
 2744                 break;
 2745 
 2746         case METEORSSIGNAL:
 2747                 sig = *(unsigned int *)ap->a_data;
 2748 
 2749                 if (!_SIG_VALID(sig))
 2750                         return EINVAL;
 2751 
 2752                 /*
 2753                  * Historically, applications used METEOR_SIG_MODE_MASK
 2754                  * to reset signal delivery.
 2755                  */
 2756                 if (sig == METEOR_SIG_MODE_MASK)
 2757                         sig = 0;
 2758 
 2759                 crit_enter();
 2760                 sc->enc_proc = sig ? curproc : NULL;
 2761                 sc->enc_signal = sig;
 2762                 crit_exit();
 2763                 break;
 2764 
 2765         case RADIO_GETFREQ:
 2766                 /* Convert from kHz to MHz * 100 */
 2767                 freq = sc->tuner_freq / 10;
 2768 
 2769                 *(unsigned int *)ap->a_data = freq;
 2770                 break;
 2771 
 2772         case RADIO_SETFREQ:
 2773                 if (sc->source == cxm_fm_source)
 2774                         if (cxm_pause_encoder(sc) < 0)
 2775                                 return ENXIO;
 2776 
 2777                 /* Convert from MHz * 100 to kHz */
 2778                 freq = *(unsigned int *)ap->a_data * 10;
 2779 
 2780                 if (cxm_tuner_select_frequency(sc, cxm_tuner_fm_freq_type,
 2781                                                freq) < 0)
 2782                         return ENXIO;
 2783 
 2784                 /*
 2785                  * Explicitly wait for the tuner lock so we
 2786                  * can indicate if there's a station present.
 2787                  */
 2788                 if (cxm_tuner_wait_for_lock(sc) < 0)
 2789                         return EINVAL;
 2790 
 2791                 result = cxm_encoder_wait_for_lock(sc);
 2792                 if (result < 0)
 2793                         return ENXIO;
 2794                 else if (result == 0)
 2795                         return EINVAL;
 2796 
 2797                 if (sc->source == cxm_fm_source)
 2798                         if (cxm_unpause_encoder(sc) < 0)
 2799                                 return ENXIO;
 2800                 break;
 2801 
 2802         case TVTUNER_GETAFC:
 2803                 *(int *)ap->a_data = sc->tuner_afc;
 2804                 break;
 2805 
 2806         case TVTUNER_SETAFC:
 2807                 sc->tuner_afc = (*(int *)ap->a_data != 0);
 2808                 break;
 2809 
 2810         case TVTUNER_GETTYPE:
 2811                 *(unsigned int *)ap->a_data = cxm_tuner_selected_channel_set(sc);
 2812                 break;
 2813 
 2814         case TVTUNER_SETTYPE:
 2815                 if (cxm_tuner_select_channel_set(sc, *(unsigned int *)ap->a_data) < 0)
 2816                         return EINVAL;
 2817                 break;
 2818 
 2819         case TVTUNER_SETCHNL:
 2820                 if (sc->source == cxm_tuner_source)
 2821                         if (cxm_pause_encoder(sc) < 0)
 2822                                 return ENXIO;
 2823 
 2824                 if (cxm_tuner_select_channel(sc, *(unsigned int *)ap->a_data) < 0)
 2825                         return ENXIO;
 2826 
 2827                 if (sc->tuner_afc)
 2828                         if (cxm_tuner_apply_afc(sc) < 0)
 2829                                 return EINVAL;
 2830 
 2831                 /*
 2832                  * Explicitly wait for the tuner lock so we
 2833                  * can indicate if there's a station present.
 2834                  */
 2835                 if (cxm_tuner_wait_for_lock(sc) < 0)
 2836                         return EINVAL;
 2837 
 2838                 result = cxm_encoder_wait_for_lock(sc);
 2839                 if (result < 0)
 2840                         return ENXIO;
 2841                 else if (result == 0)
 2842                         return EINVAL;
 2843 
 2844                 if (sc->source == cxm_tuner_source)
 2845                         if (cxm_unpause_encoder(sc) < 0)
 2846                                 return ENXIO;
 2847                 break;
 2848 
 2849         case TVTUNER_GETFREQ:
 2850                 /* Convert from kHz to MHz * 16 */
 2851                 freq = (sc->tuner_freq * 16) / 1000;
 2852 
 2853                 *(unsigned int *)ap->a_data = freq;
 2854                 break;
 2855 
 2856         case TVTUNER_SETFREQ:
 2857                 if (sc->source == cxm_tuner_source)
 2858                         if (cxm_pause_encoder(sc) < 0)
 2859                                 return ENXIO;
 2860 
 2861                 /* Convert from MHz * 16 to kHz */
 2862                 freq = (*(unsigned int *)ap->a_data * 1000) / 16;
 2863 
 2864                 if (cxm_tuner_select_frequency(sc, cxm_tuner_tv_freq_type,
 2865                                                freq) < 0)
 2866                         return ENXIO;
 2867 
 2868                 /*
 2869                  * Explicitly wait for the tuner lock so we
 2870                  * can indicate if there's a station present.
 2871                  */
 2872                 if (cxm_tuner_wait_for_lock(sc) < 0)
 2873                         return EINVAL;
 2874 
 2875                 result = cxm_encoder_wait_for_lock(sc);
 2876                 if (result < 0)
 2877                         return ENXIO;
 2878                 else if (result == 0)
 2879                         return EINVAL;
 2880 
 2881                 if (sc->source == cxm_tuner_source)
 2882                         if (cxm_unpause_encoder(sc) < 0)
 2883                                 return ENXIO;
 2884 
 2885                 break;
 2886 
 2887         case TVTUNER_GETSTATUS:
 2888                 status = cxm_tuner_status(sc);
 2889                 if (status < 0)
 2890                         return ENXIO;
 2891                 *(unsigned long *)ap->a_data = status & 0xff;
 2892                 break;
 2893 
 2894         case REMOTE_GETKEY:
 2895                 remote = (struct bktr_remote *)ap->a_data;
 2896                 if (cxm_ir_key(sc, (char *)remote, sizeof(*remote)) < 0)
 2897                         return ENXIO;
 2898                 break;
 2899 
 2900         default:
 2901                 return ENOTTY;
 2902         }
 2903 
 2904         return 0;
 2905 }
 2906 
 2907 static struct filterops cxm_filterops =
 2908         { FILTEROP_ISFD, NULL, cxm_filter_detach, cxm_filter };
 2909 
 2910 static int
 2911 cxm_kqfilter(struct dev_kqfilter_args *ap)
 2912 {
 2913         cdev_t dev = ap->a_head.a_dev;
 2914         struct knote *kn = ap->a_kn;
 2915         struct cxm_softc *sc;
 2916         struct klist *klist;
 2917         int unit;
 2918 
 2919         ap->a_result = 0;
 2920 
 2921         switch (kn->kn_filter) {
 2922         case EVFILT_READ:
 2923                 unit = UNIT(minor(dev));
 2924                 /* Get the device data */
 2925                 sc = (struct cxm_softc *)devclass_get_softc(cxm_devclass, unit);
 2926                 kn->kn_fop = &cxm_filterops;
 2927                 kn->kn_hook = (caddr_t)sc;
 2928                 break;
 2929         default:
 2930                 ap->a_result = EOPNOTSUPP;
 2931                 return (0);
 2932         }
 2933 
 2934         klist = &sc->enc_kq.ki_note;
 2935         knote_insert(klist, kn);
 2936 
 2937         return (0);
 2938 }
 2939 
 2940 static void
 2941 cxm_filter_detach(struct knote *kn)
 2942 {
 2943         struct cxm_softc *sc = (struct cxm_softc *)kn->kn_hook;
 2944         struct klist *klist = &sc->enc_kq.ki_note;
 2945 
 2946         knote_remove(klist, kn);
 2947 }
 2948 
 2949 static int
 2950 cxm_filter(struct knote *kn, long hint)
 2951 {
 2952         struct cxm_softc *sc = (struct cxm_softc *)kn->kn_hook;
 2953         int ready = 0;
 2954 
 2955         if (sc == NULL) {
 2956                 /* the device is no longer valid/functioning */
 2957                 kn->kn_flags |= (EV_EOF | EV_NODATA);
 2958                 return (1);
 2959         }
 2960 
 2961         crit_enter();
 2962         if (sc->enc_pool.read != sc->enc_pool.write)
 2963                 ready = 1;
 2964         crit_exit();
 2965 
 2966         return (ready);
 2967 }

Cache object: 54f5327b91124f82dbe8860c7da70531


[ 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.