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