cxm(4): Fix a crash by warning if no firmware is compiled in.
[dragonfly.git] / sys / dev / video / cxm / cxm.c
blob81dbf9e23ec7c3a3a4170d5a312d39e075fd6ac1
1 /*
2 * Copyright (c) 2003, 2004, 2005
3 * John Wehle <john@feith.com>. All rights reserved.
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.
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.
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.
37 * This driver was written using the invaluable information
38 * compiled by The IvyTV Project (ivtv.sourceforge.net).
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>
58 #include <machine/clock.h>
60 #include <dev/video/meteor/ioctl_meteor.h>
61 #include <dev/video/bktr/ioctl_bt848.h>
63 #include <bus/pci/pcireg.h>
64 #include <bus/pci/pcivar.h>
66 #include <dev/video/cxm/cxm.h>
68 #include <bus/iicbus/iiconf.h>
71 * Various supported device vendors/types and their names.
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 }
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);
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);
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),
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),
109 { 0, 0 }
112 static driver_t cxm_driver = {
113 "cxm",
114 cxm_methods,
115 sizeof(struct cxm_softc),
118 static devclass_t cxm_devclass;
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;
126 #define CDEV_MAJOR 93
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
137 MODULE_DEPEND(cxm, cxm_iic, 1, 1, 1);
138 DRIVER_MODULE(cxm, pci, cxm_driver, cxm_devclass, 0, 0);
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 */
148 * Various profiles.
150 static struct cxm_codec_profile vcd_ntsc_profile = {
151 "MPEG-1 VideoCD NTSC video and MPEG audio",
152 CXM_FW_STREAM_TYPE_VCD,
154 352, 240, 480,
155 { 10, 12, 21 },
158 { 1, 1150000, 0 },
159 { 1, 15, 3},
161 * Spatial filter = Manual, Temporal filter = Manual
162 * Median filter = Horizontal / Vertical
163 * Spatial filter value = 1, Temporal filter value = 4
165 { 0, 3, 1, 4 },
166 44100
169 static struct cxm_codec_profile vcd_pal_profile = {
170 "MPEG-1 VideoCD PAL video and MPEG audio",
171 CXM_FW_STREAM_TYPE_VCD,
173 352, 288, 576,
174 { 6, 17, 22 },
177 { 1, 1150000, 0 },
178 { 1, 12, 3},
180 * Spatial filter = Manual, Temporal filter = Manual
181 * Median filter = Horizontal / Vertical
182 * Spatial filter value = 1, Temporal filter value = 4
184 { 0, 3, 1, 4 },
185 44100
188 static struct cxm_codec_profile svcd_ntsc_profile = {
189 "MPEG-2 SuperVCD NTSC video and MPEG audio",
190 CXM_FW_STREAM_TYPE_SVCD,
192 480, 480, 480,
193 { 10, 12, 21 },
196 /* 2.5 Mb/s peak limit to keep bbdmux followed by mplex -f 4 happy */
197 { 0, 1150000, 2500000 },
198 { 1, 15, 3},
200 * Spatial filter = Manual, Temporal filter = Manual
201 * Median filter = Horizontal / Vertical
202 * Spatial filter value = 1, Temporal filter value = 4
204 { 0, 3, 1, 4 },
205 44100
208 static struct cxm_codec_profile svcd_pal_profile = {
209 "MPEG-2 SuperVCD PAL video and MPEG audio",
210 CXM_FW_STREAM_TYPE_SVCD,
212 480, 576, 576,
213 { 6, 17, 22 },
216 /* 2.5 Mb/s peak limit to keep bbdmux followed by mplex -f 4 happy */
217 { 0, 1150000, 2500000 },
218 { 1, 12, 3},
220 * Spatial filter = Manual, Temporal filter = Manual
221 * Median filter = Horizontal / Vertical
222 * Spatial filter value = 1, Temporal filter value = 4
224 { 0, 3, 1, 4 },
225 44100
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,
232 352, 480, 480,
233 { 10, 12, 21 },
236 { 0, 4000000, 4520000 }, /* 4 hours on 8.54 GB media */
237 { 1, 15, 3},
239 * Spatial filter = Manual, Temporal filter = Manual
240 * Median filter = Horizontal / Vertical
241 * Spatial filter value = 1, Temporal filter value = 4
243 { 0, 3, 1, 4 },
244 48000
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,
251 352, 576, 576,
252 { 6, 17, 22 },
255 { 0, 4000000, 4520000 }, /* 4 hours on 8.54 GB media */
256 { 1, 12, 3},
258 * Spatial filter = Manual, Temporal filter = Manual
259 * Median filter = Horizontal / Vertical
260 * Spatial filter value = 1, Temporal filter value = 4
262 { 0, 3, 1, 4 },
263 48000
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,
270 720, 480, 480,
271 { 10, 12, 21 },
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},
278 * Spatial filter = Manual, Temporal filter = Manual
279 * Median filter = Horizontal / Vertical
280 * Spatial filter value = 1, Temporal filter value = 4
282 { 0, 3, 1, 4 },
283 48000
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,
290 720, 576, 576,
291 { 6, 17, 22 },
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},
298 * Spatial filter = Manual, Temporal filter = Manual
299 * Median filter = Horizontal / Vertical
300 * Spatial filter value = 1, Temporal filter value = 4
302 { 0, 3, 1, 4 },
303 48000
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
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)
325 unsigned int i;
326 unsigned int mailbox;
327 uint32_t completed_command;
328 uint32_t flags;
330 if (nparameters > CXM_MBX_MAX_PARAMETERS) {
331 device_printf(sc->dev, "too many parameters for mailbox\n");
332 return -1;
335 mailbox = 0;
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;
343 case cxm_enc_mailbox:
344 mailbox = sc->enc_mbx
345 + CXM_MBX_FW_CMD_MAILBOX *sizeof(struct cxm_mailbox);
346 break;
348 default:
349 return -1;
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;
361 * Mail boxes containing certain completed commands
362 * for which the results are never needed can be reused.
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));
373 * DMA results are always check by reading the
374 * DMA status register ... never by checking
375 * the mailbox after the command has completed.
378 if (completed_command == CXM_FW_CMD_SCHED_DMA_TO_HOST)
379 break;
382 mailbox += sizeof(struct cxm_mailbox);
385 if (i >= CXM_MBX_FW_CMD_MAILBOXES) {
386 crit_exit();
387 return -1;
390 CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags),
391 CXM_MBX_FLAG_IN_USE);
394 * PCI writes may be buffered so force the
395 * write to complete by reading the last
396 * location written.
399 CSR_READ_4(sc, mailbox + offsetof(struct cxm_mailbox, flags));
401 crit_exit();
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);
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));
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);
420 CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags),
421 CXM_MBX_FLAG_IN_USE | CXM_MBX_FLAG_DRV_DONE);
423 return mailbox;
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)
432 const char *wmesg;
433 unsigned int *bmp;
434 unsigned int i;
435 unsigned int mailbox;
436 uint32_t flags;
437 uint32_t result;
439 bmp = NULL;
440 wmesg = "";
442 switch (mbx_name) {
443 case cxm_dec_mailbox:
444 bmp = &sc->dec_mbx;
445 wmesg = "cxmdfw";
446 break;
448 case cxm_enc_mailbox:
449 bmp = &sc->enc_mbx;
450 wmesg = "cxmefw";
451 break;
453 default:
454 return -1;
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;
464 /* Give the firmware a chance to start processing the request */
465 tsleep(bmp, 0, wmesg, hz / 100);
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;
474 /* Wait for 10ms */
475 tsleep(bmp, 0, wmesg, hz / 100);
478 if (i >= 100) {
479 device_printf(sc->dev, "timeout\n");
480 return -1;
483 result = CSR_READ_4(sc,
484 mailbox
485 + offsetof(struct cxm_mailbox, result));
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));
494 CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags), 0);
496 return result == 0 ? 0 : -1;
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)
505 unsigned int i;
506 unsigned int mailbox;
507 uint32_t flags;
508 uint32_t result;
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;
516 /* Wait for 10ms */
517 DELAY(10000);
520 if (i >= 100) {
521 device_printf(sc->dev, "no free mailboxes\n");
522 return -1;
525 /* Give the firmware a chance to start processing the request */
526 DELAY(10000);
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;
535 /* Wait for 10ms */
536 DELAY(10000);
539 if (i >= 100) {
540 device_printf(sc->dev, "timeout\n");
541 return -1;
544 result = CSR_READ_4(sc,
545 mailbox
546 + offsetof(struct cxm_mailbox, result));
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));
555 CSR_WRITE_4(sc, mailbox + offsetof(struct cxm_mailbox, flags), 0);
557 return result == 0 ? 0 : -1;
561 static int
562 cxm_stop_firmware(struct cxm_softc *sc)
565 if (cxm_firmware_command_nosleep(sc, cxm_enc_mailbox,
566 CXM_FW_CMD_ENC_HALT_FW, NULL, 0) < 0)
567 return -1;
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;
575 /* Wait for 10ms */
576 DELAY(10000);
578 return 0;
582 static void
583 cxm_set_irq_mask(struct cxm_softc *sc, uint32_t mask)
585 crit_enter();
587 CSR_WRITE_4(sc, CXM_REG_IRQ_MASK, mask);
590 * PCI writes may be buffered so force the
591 * write to complete by reading the last
592 * location written.
595 CSR_READ_4(sc, CXM_REG_IRQ_MASK);
597 sc->irq_mask = mask;
599 crit_exit();
603 static void
604 cxm_set_irq_status(struct cxm_softc *sc, uint32_t status)
607 CSR_WRITE_4(sc, CXM_REG_IRQ_STATUS, status);
610 * PCI writes may be buffered so force the
611 * write to complete by reading the last
612 * location written.
615 CSR_READ_4(sc, CXM_REG_IRQ_STATUS);
619 static int
620 cxm_stop_hardware(struct cxm_softc *sc)
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;
629 /* Halt the firmware */
630 if (sc->enc_mbx != -1) {
631 if (cxm_stop_firmware(sc) < 0)
632 return -1;
635 /* Mask all interrupts */
636 cxm_set_irq_mask(sc, 0xffffffff);
638 /* Stop VDM */
639 CSR_WRITE_4(sc, CXM_REG_VDM, CXM_CMD_VDM_STOP);
641 /* Stop AO */
642 CSR_WRITE_4(sc, CXM_REG_AO, CXM_CMD_AO_STOP);
644 /* Ping (?) APU */
645 CSR_WRITE_4(sc, CXM_REG_APU, CXM_CMD_APU_PING);
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);
652 /* Reset Hw Blocks */
653 CSR_WRITE_4(sc, CXM_REG_HW_BLOCKS, CXM_CMD_HW_BLOCKS_RST);
655 /* Stop SPU */
656 CSR_WRITE_4(sc, CXM_REG_SPU, CXM_CMD_SPU_STOP);
658 /* Wait for 10ms */
659 DELAY(10000);
661 return 0;
665 static int
666 cxm_download_firmware(struct cxm_softc *sc)
668 unsigned int i;
669 const uint32_t *fw;
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;
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++);
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++);
692 return 0;
696 static int
697 cxm_init_hardware(struct cxm_softc *sc)
699 unsigned int i;
700 unsigned int mailbox;
701 uint32_t parameter;
703 if (cxm_stop_hardware(sc) < 0)
704 return -1;
706 /* Initialize encoder SDRAM pre-charge */
707 CSR_WRITE_4(sc, CXM_REG_ENC_SDRAM_PRECHARGE,
708 CXM_CMD_SDRAM_PRECHARGE_INIT);
710 /* Initialize encoder SDRAM refresh to 1us */
711 CSR_WRITE_4(sc, CXM_REG_ENC_SDRAM_REFRESH,
712 CXM_CMD_SDRAM_REFRESH_INIT);
714 /* Initialize decoder SDRAM pre-charge */
715 CSR_WRITE_4(sc, CXM_REG_DEC_SDRAM_PRECHARGE,
716 CXM_CMD_SDRAM_PRECHARGE_INIT);
718 /* Initialize decoder SDRAM refresh to 1us */
719 CSR_WRITE_4(sc, CXM_REG_DEC_SDRAM_REFRESH,
720 CXM_CMD_SDRAM_REFRESH_INIT);
722 /* Wait for 600ms */
723 DELAY(600000);
725 if (cxm_download_firmware(sc) < 0)
726 return -1;
728 /* Enable SPU */
729 CSR_WRITE_4(sc, CXM_REG_SPU,
730 CSR_READ_4(sc, CXM_REG_SPU) & CXM_MASK_SPU_ENABLE);
732 /* Wait for 1 second */
733 DELAY(1000000);
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));
742 /* Wait for 1 second */
743 DELAY(1000000);
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;
754 if (i >= CXM_MEM_ENC_SIZE)
755 return -1;
757 sc->enc_mbx = mailbox + i + 16;
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;
769 if (i >= CXM_MEM_DEC_SIZE)
770 return -1;
772 sc->dec_mbx = mailbox + i + 16;
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;
782 device_printf(sc->dev, "encoder firmware version %#x\n",
783 (unsigned int)parameter);
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;
793 device_printf(sc->dev, "decoder firmware version %#x\n",
794 (unsigned int)parameter);
797 return 0;
801 static int
802 cxm_configure_encoder(struct cxm_softc *sc)
804 int fps;
805 unsigned int i;
806 uint32_t parameters[12];
807 const struct cxm_codec_profile *cpp;
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;
818 default:
819 fps = 25;
820 break;
822 else
823 fps = cxm_saa7115_detected_fps(sc);
825 if (fps < 0)
826 return -1;
828 if (sc->profile->fps != fps) {
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.
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;
843 if (i >= NUM_ELEMENTS(codec_profiles))
844 return -1;
846 sc->profile = codec_profiles[i];
849 cpp = sc->profile;
851 if (cxm_saa7115_configure(sc,
852 cpp->width, cpp->source_height, fps,
853 cpp->audio_sample_rate) < 0)
854 return -1;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
957 * assign audio properties
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;
965 if (i >= NUM_ELEMENTS(codec_audio_formats))
966 return -1;
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;
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;
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;
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;
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;
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;
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;
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;
1049 return 0;
1053 static int
1054 cxm_start_encoder(struct cxm_softc *sc)
1056 uint32_t parameters[4];
1057 uint32_t subtype;
1058 uint32_t type;
1061 if (sc->encoding)
1062 return 0;
1064 if (cxm_configure_encoder(sc) < 0)
1065 return -1;
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;
1074 /* Clear pending encoder interrupts (which are currently masked) */
1075 cxm_set_irq_status(sc, CXM_IRQ_ENC);
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;
1087 if (cxm_saa7115_mute(sc) < 0)
1088 return -1;
1089 if (cxm_msp_mute(sc) < 0)
1090 return -1;
1092 if (cxm_firmware_command(sc, cxm_enc_mailbox,
1093 CXM_FW_CMD_INITIALIZE_VIDEO_INPUT,
1094 NULL, 0) < 0)
1095 return -1;
1097 if (cxm_saa7115_unmute(sc) < 0)
1098 return -1;
1099 if (cxm_msp_unmute(sc) < 0)
1100 return -1;
1102 /* Wait for 100ms */
1103 tsleep(&sc->encoding, 0, "cxmce", hz / 10);
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);
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;
1119 sc->enc_pool.offset = 0;
1120 sc->enc_pool.read = 0;
1121 sc->enc_pool.write = 0;
1123 sc->encoding_eos = 0;
1125 sc->encoding = 1;
1127 /* Enable interrupts */
1128 cxm_set_irq_mask(sc, sc->irq_mask & ~CXM_IRQ_ENC);
1130 return 0;
1134 static int
1135 cxm_stop_encoder(struct cxm_softc *sc)
1137 uint32_t parameters[4];
1138 uint32_t subtype;
1139 uint32_t type;
1141 if (!sc->encoding)
1142 return 0;
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);
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;
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();
1165 if (sc->mpeg && !sc->encoding_eos)
1166 device_printf(sc->dev, "missing encoder EOS\n");
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;
1178 /* Disable interrupts */
1179 cxm_set_irq_mask(sc, sc->irq_mask | CXM_IRQ_ENC);
1181 sc->encoding = 0;
1183 return 0;
1187 static int
1188 cxm_pause_encoder(struct cxm_softc *sc)
1190 uint32_t parameter;
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;
1198 return 0;
1202 static int
1203 cxm_unpause_encoder(struct cxm_softc *sc)
1205 uint32_t parameter;
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;
1213 return 0;
1217 static unsigned int
1218 cxm_encoder_fixup_byte_order(struct cxm_softc *sc,
1219 unsigned int current, size_t offset)
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;
1232 switch (sc->enc_pool.bufs[current].byte_order) {
1233 case cxm_device_mpeg_byte_order:
1236 * Convert each 32 bit word to the proper byte ordering.
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;
1246 case cxm_device_yuv12_byte_order:
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).
1255 scratch = (current + (CXM_SG_BUFFERS - 1)) % CXM_SG_BUFFERS;
1257 if (offset) {
1258 current = scratch;
1259 break;
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);
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++;
1287 ptr += CXM_MACROBLOCK_WIDTH / sizeof(*ptr);
1291 sc->enc_pool.bufs[scratch].size
1292 = sc->enc_pool.bufs[current].size;
1294 current = scratch;
1295 break;
1297 default:
1298 break;
1301 sc->enc_pool.bufs[current].byte_order = cxm_host_byte_order;
1303 return current;
1307 static void
1308 cxm_encoder_dma_discard(struct cxm_softc *sc)
1310 uint32_t parameters[3];
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;
1324 sc->encoding_dma = -1;
1328 static void
1329 cxm_encoder_dma_done(struct cxm_softc *sc)
1331 int buffers_pending;
1332 uint32_t status;
1334 if (!sc->encoding_dma) {
1335 device_printf(sc->dev,
1336 "encoder dma not already in progress\n");
1337 return;
1340 buffers_pending = sc->encoding_dma;
1341 sc->encoding_dma = 0;
1343 if (buffers_pending < 0)
1344 return;
1346 status = CSR_READ_4(sc, CXM_REG_DMA_STATUS) & 0x0000000f;
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;
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();
1362 /* signal anyone requesting notification */
1363 if (sc->enc_proc)
1364 ksignal (sc->enc_proc, sc->enc_signal);
1366 /* wakeup anyone waiting for data */
1367 wakeup(&sc->enc_pool.read);
1369 /* wakeup anyone polling for data */
1370 selwakeup(&sc->enc_sel);
1374 static void
1375 cxm_encoder_dma_request(struct cxm_softc *sc)
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];
1394 if (sc->encoding_dma) {
1395 device_printf(sc->dev, "encoder dma already in progress\n");
1396 cxm_encoder_dma_discard(sc);
1397 return;
1400 mailbox = sc->enc_mbx
1401 + CXM_MBX_FW_DMA_MAILBOX * sizeof(struct cxm_mailbox);
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)
1411 byte_order = cxm_device_mpeg_byte_order;
1412 max_sg_segment = CXM_SG_SEGMENT;
1413 nrequests = 0;
1414 type = parameters[0];
1416 switch (type) {
1417 case 0: /* MPEG */
1418 requests[nrequests].offset = parameters[1];
1419 requests[nrequests++].size = parameters[2];
1420 break;
1422 case 1: /* YUV */
1423 byte_order = cxm_device_yuv12_byte_order;
1426 * Simplify macroblock unpacking by ensuring
1427 * that strips don't span buffers.
1430 #if CXM_MACROBLOCK_SIZE % 256
1431 # error CXM_MACROBLOCK_SIZE not a multiple of 256
1432 #endif
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;
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;
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;
1457 * Determine the number of buffers free at this * instant *
1458 * taking into consideration that the ring buffer wraps.
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();
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.
1474 buffers_pending = 0;
1475 current = sc->enc_pool.write;
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;
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;
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;
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;
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;
1512 /* Mark the last transfer in the list */
1513 sc->enc_sg.vaddr[buffers_pending - 1].size |= 0x80000000;
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;
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.
1535 sc->encoding_dma = buffers_pending;
1539 static int
1540 cxm_encoder_wait_for_lock(struct cxm_softc *sc)
1542 int muted;
1543 int locked;
1544 int result;
1546 locked = 1;
1549 * Wait for the tuner to lock.
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;
1558 * Wait for the video decoder to lock.
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;
1569 * Wait for the audio decoder to lock.
1571 if (sc->source == cxm_tuner_source) {
1572 muted = cxm_msp_is_muted(sc);
1574 result = cxm_msp_autodetect_standard(sc);
1575 if (result < 0)
1576 return result;
1577 else if (result == 0)
1578 locked = 0;
1580 if (muted == 0 && cxm_msp_unmute(sc) < 0)
1581 return -1;
1584 return locked;
1588 static void
1589 cxm_mapmem(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1591 bus_addr_t *busaddrp;
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.
1599 busaddrp = (bus_addr_t *)arg;
1600 *busaddrp = segs->ds_addr;
1605 * the boot time probe routine.
1607 static int
1608 cxm_probe(device_t dev)
1610 struct cxm_dev *t;
1612 t = cxm_devs;
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;
1620 t++;
1623 return ENXIO;
1628 * the attach routine.
1630 static int
1631 cxm_attach(device_t dev)
1633 int error;
1634 int rid;
1635 int unit;
1636 unsigned int i;
1637 uint32_t command;
1638 struct cxm_softc *sc;
1640 /* Get the device data */
1641 sc = device_get_softc(dev);
1642 unit = device_get_unit(dev);
1644 sc->dev = dev;
1645 sc->type = cxm_iTVC15_type;
1647 switch(pci_get_device(dev)) {
1648 case PCI_PRODUCT_ICOMPRESSION_ITVC16:
1649 sc->type = cxm_iTVC16_type;
1650 break;
1652 default:
1653 break;
1657 * Enable bus mastering and memory mapped I/O.
1659 pci_enable_busmaster(dev);
1660 pci_enable_io(dev, SYS_RES_MEMORY);
1661 command = pci_read_config(dev, PCIR_COMMAND, 4);
1663 if (!(command & PCIM_CMD_MEMEN)) {
1664 device_printf(dev, "failed to enable memory mappings\n");
1665 error = ENXIO;
1666 goto fail;
1670 * Map control/status registers.
1672 rid = CXM_RID;
1673 sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
1674 0, ~0, 1, RF_ACTIVE);
1676 if (!sc->mem_res) {
1677 device_printf(dev, "could not map memory\n");
1678 error = ENXIO;
1679 goto fail;
1682 sc->btag = rman_get_bustag(sc->mem_res);
1683 sc->bhandle = rman_get_bushandle(sc->mem_res);
1686 * Attach the I2C bus.
1688 sc->cxm_iic = device_add_child(dev, "cxm_iic", unit);
1690 if (!sc->cxm_iic) {
1691 device_printf(dev, "could not add cxm_iic\n");
1692 error = ENXIO;
1693 goto fail;
1696 error = device_probe_and_attach(sc->cxm_iic);
1698 if (error) {
1699 device_printf(dev, "could not attach cxm_iic\n");
1700 goto fail;
1704 * Initialize the tuner.
1706 if (cxm_tuner_init(sc) < 0) {
1707 device_printf(dev, "could not initialize tuner\n");
1708 error = ENXIO;
1709 goto fail;
1713 * Initialize the SAA7115.
1715 if (cxm_saa7115_init(sc) < 0) {
1716 device_printf(dev, "could not initialize video decoder\n");
1717 error = ENXIO;
1718 goto fail;
1722 * Initialize the MSP3400.
1724 if (cxm_msp_init(sc) < 0) {
1725 device_printf(dev, "could not initialize audio decoder\n");
1726 error = ENXIO;
1727 goto fail;
1731 * Initialize the IR Remote.
1733 if (cxm_ir_init(sc) < 0) {
1734 device_printf(dev, "could not initialize IR remote\n");
1735 error = ENXIO;
1736 goto fail;
1739 sc->dec_mbx = -1;
1740 sc->enc_mbx = -1;
1743 * Disable the Conexant device.
1745 * This is done * after * attaching the I2C bus so
1746 * cxm_stop_hardware can mute the video and audio
1747 * decoders.
1749 cxm_stop_hardware(sc);
1752 * Allocate our interrupt.
1754 rid = 0;
1755 sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
1756 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
1758 if (sc->irq_res == NULL) {
1759 device_printf(dev, "could not map interrupt\n");
1760 error = ENXIO;
1761 goto fail;
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;
1773 * Allocate a DMA tag for the parent bus.
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;
1787 * Allocate a DMA tag for the encoder buffers.
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;
1801 for (i = 0; i < CXM_SG_BUFFERS; i++) {
1804 * Allocate the encoder buffer.
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;
1817 * Map the encoder buffer.
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;
1832 * Allocate a DMA tag for the scatter / gather list.
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;
1848 * Allocate the scatter / gather list.
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;
1859 * Map the scatter / gather list.
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;
1871 * Initialize the hardware.
1873 if (cxm_init_hardware(sc) < 0) {
1874 device_printf(dev, "could not initialize hardware\n");
1875 error = ENXIO;
1876 goto fail;
1879 sc->profile = &dvd_full_d1_ntsc_profile;
1881 sc->source = cxm_tuner_source;
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);
1889 return 0;
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);
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);
1910 if (sc->enc_pool.dmat)
1911 bus_dma_tag_destroy(sc->enc_pool.dmat);
1913 if (sc->parent_dmat)
1914 bus_dma_tag_destroy(sc->parent_dmat);
1917 * Detach the I2C bus.
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.
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.
1927 bus_generic_detach(dev);
1928 if (sc->cxm_iic)
1929 device_delete_child(dev, sc->cxm_iic);
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);
1938 return error;
1942 * the detach routine.
1944 static int
1945 cxm_detach(device_t dev)
1947 unsigned int i;
1948 struct cxm_softc *sc;
1949 device_t child;
1951 /* Get the device data */
1952 sc = device_get_softc(dev);
1954 /* Disable the Conexant device. */
1955 cxm_stop_hardware(sc);
1957 /* Unregister the /dev/cxmN device. */
1958 dev_ops_remove(&cxm_ops, 0, device_get_unit(dev));
1961 * Deallocate scatter / gather list and buffers.
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);
1966 bus_dma_tag_destroy(sc->enc_sg.dmat);
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);
1975 bus_dma_tag_destroy(sc->enc_pool.dmat);
1977 bus_dma_tag_destroy(sc->parent_dmat);
1980 * Detach the I2C bus.
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.
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.
1990 * Remember the child before detaching so we can
1991 * delete it (bus_generic_detach indirectly zeroes
1992 * sc->child_dev).
1994 child = sc->cxm_iic;
1995 bus_generic_detach(dev);
1996 if (child)
1997 device_delete_child(dev, child);
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);
2004 return 0;
2008 * the shutdown routine.
2010 static int
2011 cxm_shutdown(device_t dev)
2013 struct cxm_softc *sc = device_get_softc(dev);
2015 /* Disable the Conexant device. */
2016 cxm_stop_hardware(sc);
2018 return 0;
2022 * the interrupt routine.
2024 static void
2025 cxm_intr(void *arg)
2027 uint32_t status;
2028 struct cxm_softc *sc;
2030 /* Get the device data */
2031 sc = (struct cxm_softc *)arg;
2033 status = CSR_READ_4(sc, CXM_REG_IRQ_STATUS);
2035 status &= ~sc->irq_mask;
2037 if (!status)
2038 return;
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);
2044 if (status & CXM_IRQ_ENC_DMA_REQUEST)
2045 cxm_encoder_dma_request(sc);
2047 if (status & CXM_IRQ_ENC_EOS) {
2048 sc->encoding_eos = 1;
2049 wakeup(&sc->encoding_eos);
2052 cxm_set_irq_status(sc, status);
2057 * the child detached routine.
2059 static void
2060 cxm_child_detached(device_t dev, device_t child)
2062 struct cxm_softc *sc;
2064 /* Get the device data */
2065 sc = device_get_softc(dev);
2067 if (child == sc->cxm_iic)
2068 sc->cxm_iic = NULL;
2072 static int
2073 cxm_read_ivar(device_t dev, device_t child, int index, uintptr_t* val)
2075 struct cxm_softc *sc;
2077 /* Get the device data */
2078 sc = device_get_softc(dev);
2080 switch (index) {
2081 case CXM_IVAR_BHANDLE:
2082 *(bus_space_handle_t **)val = &sc->bhandle;
2083 break;
2085 case CXM_IVAR_BTAG:
2086 *(bus_space_tag_t **)val = &sc->btag;
2087 break;
2089 case CXM_IVAR_IICBUS:
2090 *(device_t **)val = &sc->iicbus;
2091 break;
2093 default:
2094 return ENOENT;
2097 return 0;
2101 static int
2102 cxm_write_ivar(device_t dev, device_t child, int index, uintptr_t val)
2104 struct cxm_softc *sc;
2106 /* Get the device data */
2107 sc = device_get_softc(dev);
2109 switch (index) {
2110 case CXM_IVAR_BHANDLE:
2111 return EINVAL;
2113 case CXM_IVAR_BTAG:
2114 return EINVAL;
2116 case CXM_IVAR_IICBUS:
2117 if (sc->iicbus)
2118 return EINVAL;
2119 sc->iicbus = val ? *(device_t *)val : NULL;
2120 break;
2122 default:
2123 return ENOENT;
2126 return 0;
2130 /*---------------------------------------------------------
2132 ** Conexant iTVC15 / iTVC16 character device driver routines
2134 **---------------------------------------------------------
2137 #define UNIT(x) ((x) & 0x0f)
2138 #define FUNCTION(x) (x >> 4)
2144 cxm_open(struct dev_open_args *ap)
2146 cdev_t dev = ap->a_head.a_dev;
2147 int unit;
2148 struct cxm_softc *sc;
2150 unit = UNIT(minor(dev));
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;
2159 if (sc->is_opened)
2160 return EBUSY;
2162 sc->is_opened = 1;
2163 sc->mpeg = 1;
2165 /* Record that the device is now busy */
2166 device_busy(devclass_get_device(cxm_devclass, unit));
2168 return 0;
2176 cxm_close(struct dev_close_args *ap)
2178 cdev_t dev = ap->a_head.a_dev;
2179 int unit;
2180 struct cxm_softc *sc;
2182 unit = UNIT(minor(dev));
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;
2191 if (cxm_stop_encoder(sc) < 0)
2192 return ENXIO;
2194 sc->enc_pool.offset = 0;
2195 sc->enc_pool.read = 0;
2196 sc->enc_pool.write = 0;
2198 sc->enc_proc = NULL;
2199 sc->enc_signal = 0;
2201 device_unbusy(devclass_get_device(cxm_devclass, unit));
2203 sc->is_opened = 0;
2205 return 0;
2213 cxm_read(struct dev_read_args *ap)
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;
2226 unit = UNIT(minor(dev));
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;
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;
2243 buffers_available = 0;
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;
2255 * Determine the number of buffers available at this * instant *
2256 * taking in consideration that the ring buffer wraps.
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();
2263 offset = sc->enc_pool.offset;
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) {
2269 current = cxm_encoder_fixup_byte_order (sc, i, offset);
2271 nbytes = sc->enc_pool.bufs[current].size - offset;
2273 /* Don't transfer more than requested */
2274 if (nbytes > ap->a_uio->uio_resid)
2275 nbytes = ap->a_uio->uio_resid;
2277 error = uiomove(sc->enc_pool.bufs[current].vaddr + offset,
2278 nbytes, ap->a_uio);
2279 if (error)
2280 return error;
2282 offset += nbytes;
2284 /* Handle a partial read of a buffer */
2285 if (!ap->a_uio->uio_resid && offset != sc->enc_pool.bufs[i].size)
2286 break;
2288 offset = 0;
2291 sc->enc_pool.offset = offset;
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();
2299 return 0;
2307 cxm_ioctl(struct dev_ioctl_args *ap)
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;
2326 unit = UNIT(minor(dev));
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;
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;
2342 case cxm_line_in_source_composite:
2343 case cxm_line_in_source_svideo:
2344 *(int *) ap->a_data = AUDIO_EXTERN;
2345 break;
2347 case cxm_fm_source:
2348 *(int *) ap->a_data = AUDIO_INTERN;
2349 break;
2351 default:
2352 return ENXIO;
2355 if (cxm_msp_is_muted(sc) == 1)
2356 *(int *) ap->a_data |= AUDIO_MUTE;
2357 break;
2359 case BT848_SAUDIO:
2360 source = cxm_unknown_source;
2362 switch (*(int *) ap->a_data) {
2363 case AUDIO_TUNER:
2364 source = cxm_tuner_source;
2365 break;
2367 case AUDIO_EXTERN:
2368 source = cxm_line_in_source_composite;
2369 break;
2371 case AUDIO_INTERN:
2372 source = cxm_fm_source;
2373 break;
2375 case AUDIO_MUTE:
2376 if (cxm_msp_mute(sc) < 0)
2377 return ENXIO;
2378 return 0;
2380 case AUDIO_UNMUTE:
2381 if (cxm_msp_unmute(sc) < 0)
2382 return ENXIO;
2383 return 0;
2385 default:
2386 return EINVAL;
2389 if (sc->encoding) {
2392 * Switching between audio + video and audio only
2393 * subtypes isn't supported while encoding.
2396 if (source != sc->source
2397 && (source == cxm_fm_source
2398 || sc->source == cxm_fm_source))
2399 return EBUSY;
2402 if (cxm_pause_encoder(sc) < 0)
2403 return ENXIO;
2405 if (cxm_msp_select_source(sc, source) < 0)
2406 return ENXIO;
2408 if (source == cxm_fm_source)
2409 sc->source = source;
2411 result = cxm_encoder_wait_for_lock(sc);
2412 if (result < 0)
2413 return ENXIO;
2414 else if (result == 0)
2415 return EINVAL;
2417 if (cxm_unpause_encoder(sc) < 0)
2418 return ENXIO;
2419 break;
2421 case BT848_GBRIG:
2422 brightness = cxm_saa7115_get_brightness(sc);
2424 if (brightness < 0)
2425 return ENXIO;
2428 * Brooktree brightness:
2429 * 0x80 = -50.0%, 0x00 = +0.0%, 0x7f = +49.6%
2431 *(int *)ap->a_data = (int)(unsigned char)brightness - 128;
2432 break;
2434 case BT848_SBRIG:
2437 * Brooktree brightness:
2438 * 0x80 = -50.0%, 0x00 = +0.0%, 0x7f = +49.6%
2440 brightness = *(int *)ap->a_data + 128;
2442 if (cxm_saa7115_set_brightness(sc, brightness) < 0)
2443 return ENXIO;
2444 break;
2446 case METEORGBRIG:
2447 brightness = cxm_saa7115_get_brightness(sc);
2449 if (brightness < 0)
2450 return ENXIO;
2452 *(unsigned char *)ap->a_data = (unsigned char)brightness;
2453 break;
2455 case METEORSBRIG:
2456 brightness = *(unsigned char *)ap->a_data;
2458 if (cxm_saa7115_set_brightness(sc, brightness) < 0)
2459 return ENXIO;
2460 break;
2462 case BT848_GCSAT:
2463 chroma_saturation = cxm_saa7115_get_chroma_saturation(sc);
2465 if (chroma_saturation < 0)
2466 return ENXIO;
2469 * Brooktree chroma saturation:
2470 * 0x000 = 0%, 0x0fe = 100%, 0x1ff = 201.18%
2472 *(int *)ap->a_data = ((signed char)chroma_saturation > 0)
2473 ? (chroma_saturation * 4 - 2) : 0;
2474 break;
2476 case BT848_SCSAT:
2479 * Brooktree chroma saturation:
2480 * 0x000 = 0%, 0x0fe = 100%, 0x1ff = 201.18%
2482 chroma_saturation = (*(int *)ap->a_data & 0x1ff) < 510
2483 ? ((*(int *)ap->a_data & 0x1ff) + 2) / 4 : 127;
2485 if (cxm_saa7115_set_chroma_saturation(sc, chroma_saturation)
2486 < 0)
2487 return ENXIO;
2489 break;
2491 case METEORGCSAT:
2492 chroma_saturation = cxm_saa7115_get_chroma_saturation(sc);
2494 if (chroma_saturation < 0)
2495 return ENXIO;
2497 *(unsigned char *)ap->a_data = (unsigned char)chroma_saturation;
2498 break;
2500 case METEORSCSAT:
2501 chroma_saturation = *(unsigned char *)ap->a_data;
2503 if (cxm_saa7115_set_chroma_saturation(sc, chroma_saturation)
2504 < 0)
2505 return ENXIO;
2506 break;
2508 case METEORGCONT:
2509 contrast = cxm_saa7115_get_contrast(sc);
2511 if (contrast < 0)
2512 return ENXIO;
2514 *(unsigned char *)ap->a_data = (unsigned char)contrast;
2515 break;
2517 case METEORSCONT:
2518 contrast = *(unsigned char *)ap->a_data;
2520 if (cxm_saa7115_set_contrast(sc, contrast) < 0)
2521 return ENXIO;
2522 break;
2524 case BT848_GHUE:
2525 hue = cxm_saa7115_get_hue(sc);
2527 if (hue < 0)
2528 return ENXIO;
2530 *(int *)ap->a_data = (signed char)hue;
2531 break;
2533 case BT848_SHUE:
2534 hue = *(int *)ap->a_data;
2536 if (cxm_saa7115_set_hue(sc, hue) < 0)
2537 return ENXIO;
2538 break;
2540 case METEORGHUE:
2541 hue = cxm_saa7115_get_hue(sc);
2543 if (hue < 0)
2544 return ENXIO;
2546 *(signed char *)ap->a_data = (signed char)hue;
2547 break;
2549 case METEORSHUE:
2550 hue = *(signed char *)ap->a_data;
2552 if (cxm_saa7115_set_hue(sc, hue) < 0)
2553 return ENXIO;
2554 break;
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;
2563 case METEOR_CAP_STOP_CONT:
2564 if (cxm_stop_encoder(sc) < 0)
2565 return ENXIO;
2566 break;
2568 default:
2569 return EINVAL;
2571 break;
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;
2582 case BT848_SCAPAREA:
2583 if (sc->encoding)
2584 return EBUSY;
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;
2593 * Setting the width and height has the side effect of
2594 * chosing between the VCD, SVCD, and DVD profiles.
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;
2602 if (i >= NUM_ELEMENTS(codec_profiles))
2603 return EINVAL;
2605 sc->profile = codec_profiles[i];
2606 break;
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;
2614 case cxm_pal_50hz_source_format:
2615 *(unsigned long *)ap->a_data = BT848_IFORM_F_PALBDGHI;
2616 break;
2618 case cxm_secam_50hz_source_format:
2619 *(unsigned long *)ap->a_data = BT848_IFORM_F_SECAM;
2620 break;
2622 case cxm_pal_60hz_source_format:
2623 *(unsigned long *)ap->a_data = BT848_IFORM_F_PALM;
2624 break;
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;
2632 default:
2633 return ENXIO;
2635 break;
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;
2643 case cxm_pal_50hz_source_format:
2644 *(unsigned long *)ap->a_data = METEOR_FMT_PAL;
2645 break;
2647 case cxm_secam_50hz_source_format:
2648 *(unsigned long *)ap->a_data = METEOR_FMT_SECAM;
2649 break;
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;
2658 default:
2659 return ENXIO;
2661 break;
2663 case METEORGFPS:
2664 fps = cxm_saa7115_detected_fps(sc);
2666 if (fps < 0)
2667 return ENXIO;
2669 *(unsigned short *)ap->a_data = fps;
2670 break;
2672 case METEORGINPUT:
2673 switch (sc->source) {
2674 case cxm_tuner_source:
2675 *(unsigned long *)ap->a_data = METEOR_INPUT_DEV1;
2676 break;
2678 case cxm_line_in_source_composite:
2679 *(unsigned long *)ap->a_data = METEOR_INPUT_DEV2;
2680 break;
2682 case cxm_line_in_source_svideo:
2683 *(unsigned long *)ap->a_data = METEOR_INPUT_DEV_SVIDEO;
2684 break;
2686 default:
2687 return ENXIO;
2689 break;
2691 case METEORSINPUT:
2692 source = cxm_unknown_source;
2694 switch (*(unsigned long *)ap->a_data & 0xf000) {
2695 case METEOR_INPUT_DEV1:
2696 source = cxm_tuner_source;
2697 break;
2699 case METEOR_INPUT_DEV2:
2700 source = cxm_line_in_source_composite;
2701 break;
2703 case METEOR_INPUT_DEV_SVIDEO:
2704 source = cxm_line_in_source_svideo;
2705 break;
2707 default:
2708 return EINVAL;
2711 if (sc->encoding) {
2714 * Switching between audio + video and audio only
2715 * subtypes isn't supported while encoding.
2718 if (source != sc->source
2719 && (source == cxm_fm_source
2720 || sc->source == cxm_fm_source))
2721 return EBUSY;
2724 if (cxm_pause_encoder(sc) < 0)
2725 return ENXIO;
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;
2733 result = cxm_encoder_wait_for_lock(sc);
2734 if (result < 0)
2735 return ENXIO;
2736 else if (result == 0)
2737 return EINVAL;
2739 if (cxm_unpause_encoder(sc) < 0)
2740 return ENXIO;
2741 break;
2743 case METEORGSIGNAL:
2744 *(unsigned int *)ap->a_data = sc->enc_signal;
2745 break;
2747 case METEORSSIGNAL:
2748 sig = *(unsigned int *)ap->a_data;
2750 if (!_SIG_VALID(sig))
2751 return EINVAL;
2754 * Historically, applications used METEOR_SIG_MODE_MASK
2755 * to reset signal delivery.
2757 if (sig == METEOR_SIG_MODE_MASK)
2758 sig = 0;
2760 crit_enter();
2761 sc->enc_proc = sig ? curproc : NULL;
2762 sc->enc_signal = sig;
2763 crit_exit();
2764 break;
2766 case RADIO_GETFREQ:
2767 /* Convert from kHz to MHz * 100 */
2768 freq = sc->tuner_freq / 10;
2770 *(unsigned int *)ap->a_data = freq;
2771 break;
2773 case RADIO_SETFREQ:
2774 if (sc->source == cxm_fm_source)
2775 if (cxm_pause_encoder(sc) < 0)
2776 return ENXIO;
2778 /* Convert from MHz * 100 to kHz */
2779 freq = *(unsigned int *)ap->a_data * 10;
2781 if (cxm_tuner_select_frequency(sc, cxm_tuner_fm_freq_type,
2782 freq) < 0)
2783 return ENXIO;
2786 * Explicitly wait for the tuner lock so we
2787 * can indicate if there's a station present.
2789 if (cxm_tuner_wait_for_lock(sc) < 0)
2790 return EINVAL;
2792 result = cxm_encoder_wait_for_lock(sc);
2793 if (result < 0)
2794 return ENXIO;
2795 else if (result == 0)
2796 return EINVAL;
2798 if (sc->source == cxm_fm_source)
2799 if (cxm_unpause_encoder(sc) < 0)
2800 return ENXIO;
2801 break;
2803 case TVTUNER_GETAFC:
2804 *(int *)ap->a_data = sc->tuner_afc;
2805 break;
2807 case TVTUNER_SETAFC:
2808 sc->tuner_afc = (*(int *)ap->a_data != 0);
2809 break;
2811 case TVTUNER_GETTYPE:
2812 *(unsigned int *)ap->a_data = cxm_tuner_selected_channel_set(sc);
2813 break;
2815 case TVTUNER_SETTYPE:
2816 if (cxm_tuner_select_channel_set(sc, *(unsigned int *)ap->a_data) < 0)
2817 return EINVAL;
2818 break;
2820 case TVTUNER_SETCHNL:
2821 if (sc->source == cxm_tuner_source)
2822 if (cxm_pause_encoder(sc) < 0)
2823 return ENXIO;
2825 if (cxm_tuner_select_channel(sc, *(unsigned int *)ap->a_data) < 0)
2826 return ENXIO;
2828 if (sc->tuner_afc)
2829 if (cxm_tuner_apply_afc(sc) < 0)
2830 return EINVAL;
2833 * Explicitly wait for the tuner lock so we
2834 * can indicate if there's a station present.
2836 if (cxm_tuner_wait_for_lock(sc) < 0)
2837 return EINVAL;
2839 result = cxm_encoder_wait_for_lock(sc);
2840 if (result < 0)
2841 return ENXIO;
2842 else if (result == 0)
2843 return EINVAL;
2845 if (sc->source == cxm_tuner_source)
2846 if (cxm_unpause_encoder(sc) < 0)
2847 return ENXIO;
2848 break;
2850 case TVTUNER_GETFREQ:
2851 /* Convert from kHz to MHz * 16 */
2852 freq = (sc->tuner_freq * 16) / 1000;
2854 *(unsigned int *)ap->a_data = freq;
2855 break;
2857 case TVTUNER_SETFREQ:
2858 if (sc->source == cxm_tuner_source)
2859 if (cxm_pause_encoder(sc) < 0)
2860 return ENXIO;
2862 /* Convert from MHz * 16 to kHz */
2863 freq = (*(unsigned int *)ap->a_data * 1000) / 16;
2865 if (cxm_tuner_select_frequency(sc, cxm_tuner_tv_freq_type,
2866 freq) < 0)
2867 return ENXIO;
2870 * Explicitly wait for the tuner lock so we
2871 * can indicate if there's a station present.
2873 if (cxm_tuner_wait_for_lock(sc) < 0)
2874 return EINVAL;
2876 result = cxm_encoder_wait_for_lock(sc);
2877 if (result < 0)
2878 return ENXIO;
2879 else if (result == 0)
2880 return EINVAL;
2882 if (sc->source == cxm_tuner_source)
2883 if (cxm_unpause_encoder(sc) < 0)
2884 return ENXIO;
2886 break;
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;
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;
2901 default:
2902 return ENOTTY;
2905 return 0;
2910 cxm_poll(struct dev_poll_args *ap)
2912 cdev_t dev = ap->a_head.a_dev;
2913 int revents;
2914 int unit;
2915 struct cxm_softc *sc;
2917 unit = UNIT(minor(dev));
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;
2926 revents = 0;
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);
2935 crit_exit();
2937 return revents;