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