DEVFS - remove dev_ops_add(), dev_ops_get(), and get_dev()
[dragonfly.git] / sys / dev / video / cxm / cxm.c
CommitLineData
e9afadfd
SW
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 */
73static 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
82static int cxm_probe(device_t dev);
83static int cxm_attach(device_t dev);
84static int cxm_detach(device_t dev);
85static int cxm_shutdown(device_t dev);
86static void cxm_intr(void *arg);
87
88static void cxm_child_detached(device_t dev, device_t child);
89static int cxm_read_ivar(device_t bus, device_t dev,
90 int index, uintptr_t* val);
91static int cxm_write_ivar(device_t bus, device_t dev,
92 int index, uintptr_t val);
93
94
95static 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
112static driver_t cxm_driver = {
113 "cxm",
114 cxm_methods,
115 sizeof(struct cxm_softc),
116};
117
118static devclass_t cxm_devclass;
119
120static d_open_t cxm_open;
121static d_close_t cxm_close;
122static d_read_t cxm_read;
123static d_ioctl_t cxm_ioctl;
124static d_poll_t cxm_poll;
125
126#define CDEV_MAJOR 93
127
128static 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
137MODULE_DEPEND(cxm, cxm_iic, 1, 1, 1);
138DRIVER_MODULE(cxm, pci, cxm_driver, cxm_devclass, 0, 0);
139
140
141static 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 */
150static 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
169static 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
188static 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
208static 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
228static 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
247static 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
266static 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
286static 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
307static 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
320static unsigned int
321cxm_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
427static int
428cxm_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
500static int
501cxm_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
561static int
562cxm_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
582static void
583cxm_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
603static void
604cxm_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
619static int
620cxm_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
665static int
666cxm_download_firmware(struct cxm_softc *sc)
667{
668 unsigned int i;
669 const uint32_t *fw;
670
764b28ca
SW
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
e9afadfd
SW
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
696static int
697cxm_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
801static int
802cxm_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
1053static int
1054cxm_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
1134static int
1135cxm_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
1187static int
1188cxm_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
1202static int
1203cxm_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
1217static unsigned int
1218cxm_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
1307static void
1308cxm_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
1328static void
1329cxm_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
1374static void
1375cxm_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
1539static int
1540cxm_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
1588static void
1589cxm_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 */
1607static int
1608cxm_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 */
1630static int
1631cxm_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 */
e9afadfd 1885 sc->cxm_dev_t = make_dev(&cxm_ops, unit,
3e82b46c 1886 0, 0, 0444, "cxm%d", unit);
e9afadfd
SW
1887
1888 return 0;
1889
1890fail:
1891 if (sc->enc_sg.baddr)
1892 bus_dmamap_unload(sc->enc_sg.dmat, sc->enc_sg.dmamap);
1893 if (sc->enc_sg.vaddr)
1894 bus_dmamem_free(sc->enc_sg.dmat, sc->enc_sg.vaddr,
1895 sc->enc_sg.dmamap);
1896 if (sc->enc_sg.dmat)
1897 bus_dma_tag_destroy(sc->enc_sg.dmat);
1898
1899 for (i = 0; i < CXM_SG_BUFFERS; i++) {
1900 if (sc->enc_pool.bufs[i].baddr)
1901 bus_dmamap_unload(sc->enc_pool.dmat,
1902 sc->enc_pool.bufs[i].dmamap);
1903 if (sc->enc_pool.bufs[i].vaddr)
1904 bus_dmamem_free(sc->enc_pool.dmat,
1905 sc->enc_pool.bufs[i].vaddr,
1906 sc->enc_pool.bufs[i].dmamap);
1907 }
1908
1909 if (sc->enc_pool.dmat)
1910 bus_dma_tag_destroy(sc->enc_pool.dmat);
1911
1912 if (sc->parent_dmat)
1913 bus_dma_tag_destroy(sc->parent_dmat);
1914
1915 /*
1916 * Detach the I2C bus.
1917 *
1918 * This is done * after * deallocating the scatter / gather
1919 * list and buffers so the kernel has a better chance of
1920 * gracefully handling a memory shortage.
1921 *
1922 * Detach the children before recursively deleting
1923 * in case a child has a pointer to a grandchild
1924 * which is used by the child's detach routine.
1925 */
1926 bus_generic_detach(dev);
1927 if (sc->cxm_iic)
1928 device_delete_child(dev, sc->cxm_iic);
1929
1930 if (sc->ih_cookie)
1931 bus_teardown_intr(dev, sc->irq_res, sc->ih_cookie);
1932 if (sc->irq_res)
1933 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
1934 if (sc->mem_res)
1935 bus_release_resource(dev, SYS_RES_MEMORY, CXM_RID, sc->mem_res);
1936
1937 return error;
1938}
1939
1940/*
1941 * the detach routine.
1942 */
1943static int
1944cxm_detach(device_t dev)
1945{
1946 unsigned int i;
1947 struct cxm_softc *sc;
1948 device_t child;
1949
1950 /* Get the device data */
1951 sc = device_get_softc(dev);
1952
1953 /* Disable the Conexant device. */
1954 cxm_stop_hardware(sc);
1955
1956 /* Unregister the /dev/cxmN device. */
cd29885a 1957 dev_ops_remove_minor(&cxm_ops, /*0, */device_get_unit(dev));
e9afadfd
SW
1958
1959 /*
1960 * Deallocate scatter / gather list and buffers.
1961 */
1962 bus_dmamap_unload(sc->enc_sg.dmat, sc->enc_sg.dmamap);
1963 bus_dmamem_free(sc->enc_sg.dmat, sc->enc_sg.vaddr, sc->enc_sg.dmamap);
1964
1965 bus_dma_tag_destroy(sc->enc_sg.dmat);
1966
1967 for (i = 0; i < CXM_SG_BUFFERS; i++) {
1968 bus_dmamap_unload(sc->enc_pool.dmat,
1969 sc->enc_pool.bufs[i].dmamap);
1970 bus_dmamem_free(sc->enc_pool.dmat, sc->enc_pool.bufs[i].vaddr,
1971 sc->enc_pool.bufs[i].dmamap);
1972 }
1973
1974 bus_dma_tag_destroy(sc->enc_pool.dmat);
1975
1976 bus_dma_tag_destroy(sc->parent_dmat);
1977
1978 /*
1979 * Detach the I2C bus.
1980 *
1981 * This is done * after * deallocating the scatter / gather
1982 * list and buffers so the kernel has a better chance of
1983 * gracefully handling a memory shortage.
1984 *
1985 * Detach the children before recursively deleting
1986 * in case a child has a pointer to a grandchild
1987 * which is used by the child's detach routine.
1988 *
1989 * Remember the child before detaching so we can
1990 * delete it (bus_generic_detach indirectly zeroes
1991 * sc->child_dev).
1992 */
1993 child = sc->cxm_iic;
1994 bus_generic_detach(dev);
1995 if (child)
1996 device_delete_child(dev, child);
1997
1998 /* Deallocate resources. */
1999 bus_teardown_intr(dev, sc->irq_res, sc->ih_cookie);
2000 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
2001 bus_release_resource(dev, SYS_RES_MEMORY, CXM_RID, sc->mem_res);
2002
2003 return 0;
2004}
2005
2006/*
2007 * the shutdown routine.
2008 */
2009static int
2010cxm_shutdown(device_t dev)
2011{
2012 struct cxm_softc *sc = device_get_softc(dev);
2013
2014 /* Disable the Conexant device. */
2015 cxm_stop_hardware(sc);
2016
2017 return 0;
2018}
2019
2020/*
2021 * the interrupt routine.
2022 */
2023static void
2024cxm_intr(void *arg)
2025{
2026 uint32_t status;
2027 struct cxm_softc *sc;
2028
2029 /* Get the device data */
2030 sc = (struct cxm_softc *)arg;
2031
2032 status = CSR_READ_4(sc, CXM_REG_IRQ_STATUS);
2033
2034 status &= ~sc->irq_mask;
2035
2036 if (!status)
2037 return;
2038
2039 /* Process DMA done before handling a new DMA request or EOS */
2040 if (status & CXM_IRQ_ENC_DMA_DONE)
2041 cxm_encoder_dma_done(sc);
2042
2043 if (status & CXM_IRQ_ENC_DMA_REQUEST)
2044 cxm_encoder_dma_request(sc);
2045
2046 if (status & CXM_IRQ_ENC_EOS) {
2047 sc->encoding_eos = 1;
2048 wakeup(&sc->encoding_eos);
2049 }
2050
2051 cxm_set_irq_status(sc, status);
2052}
2053
2054
2055/*
2056 * the child detached routine.
2057 */
2058static void
2059cxm_child_detached(device_t dev, device_t child)
2060{
2061 struct cxm_softc *sc;
2062
2063 /* Get the device data */
2064 sc = device_get_softc(dev);
2065
2066 if (child == sc->cxm_iic)
2067 sc->cxm_iic = NULL;
2068}
2069
2070
2071static int
2072cxm_read_ivar(device_t dev, device_t child, int index, uintptr_t* val)
2073{
2074 struct cxm_softc *sc;
2075
2076 /* Get the device data */
2077 sc = device_get_softc(dev);
2078
2079 switch (index) {
2080 case CXM_IVAR_BHANDLE:
2081 *(bus_space_handle_t **)val = &sc->bhandle;
2082 break;
2083
2084 case CXM_IVAR_BTAG:
2085 *(bus_space_tag_t **)val = &sc->btag;
2086 break;
2087
2088 case CXM_IVAR_IICBUS:
2089 *(device_t **)val = &sc->iicbus;
2090 break;
2091
2092 default:
2093 return ENOENT;
2094 }
2095
2096 return 0;
2097}
2098
2099
2100static int
2101cxm_write_ivar(device_t dev, device_t child, int index, uintptr_t val)
2102{
2103 struct cxm_softc *sc;
2104
2105 /* Get the device data */
2106 sc = device_get_softc(dev);
2107
2108 switch (index) {
2109 case CXM_IVAR_BHANDLE:
2110 return EINVAL;
2111
2112 case CXM_IVAR_BTAG:
2113 return EINVAL;
2114
2115 case CXM_IVAR_IICBUS:
2116 if (sc->iicbus)
2117 return EINVAL;
2118 sc->iicbus = val ? *(device_t *)val : NULL;
2119 break;
2120
2121 default:
2122 return ENOENT;
2123 }
2124
2125 return 0;
2126}
2127
2128
2129/*---------------------------------------------------------
2130**
2131** Conexant iTVC15 / iTVC16 character device driver routines
2132**
2133**---------------------------------------------------------
2134*/
2135
2136#define UNIT(x) ((x) & 0x0f)
2137#define FUNCTION(x) (x >> 4)
2138
2139/*
2140 *
2141 */
2142int
2143cxm_open(struct dev_open_args *ap)
2144{
2145 cdev_t dev = ap->a_head.a_dev;
2146 int unit;
2147 struct cxm_softc *sc;
2148
2149 unit = UNIT(minor(dev));
2150
2151 /* Get the device data */
2152 sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
2153 if (sc == NULL) {
2154 /* the device is no longer valid/functioning */
2155 return ENXIO;
2156 }
2157
2158 if (sc->is_opened)
2159 return EBUSY;
2160
2161 sc->is_opened = 1;
2162 sc->mpeg = 1;
2163
2164 /* Record that the device is now busy */
2165 device_busy(devclass_get_device(cxm_devclass, unit));
2166
2167 return 0;
2168}
2169
2170
2171/*
2172 *
2173 */
2174int
2175cxm_close(struct dev_close_args *ap)
2176{
2177 cdev_t dev = ap->a_head.a_dev;
2178 int unit;
2179 struct cxm_softc *sc;
2180
2181 unit = UNIT(minor(dev));
2182
2183 /* Get the device data */
2184 sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
2185 if (sc == NULL) {
2186 /* the device is no longer valid/functioning */
2187 return ENXIO;
2188 }
2189
2190 if (cxm_stop_encoder(sc) < 0)
2191 return ENXIO;
2192
2193 sc->enc_pool.offset = 0;
2194 sc->enc_pool.read = 0;
2195 sc->enc_pool.write = 0;
2196
2197 sc->enc_proc = NULL;
2198 sc->enc_signal = 0;
2199
2200 device_unbusy(devclass_get_device(cxm_devclass, unit));
2201
2202 sc->is_opened = 0;
2203
2204 return 0;
2205}
2206
2207
2208/*
2209 *
2210 */
2211int
2212cxm_read(struct dev_read_args *ap)
2213{
2214 cdev_t dev = ap->a_head.a_dev;
2215 int buffers_available;
2216 int buffers_read;
2217 int error;
2218 int unit;
2219 unsigned int current;
2220 unsigned int i;
2221 size_t nbytes;
2222 size_t offset;
2223 struct cxm_softc *sc;
2224
2225 unit = UNIT(minor(dev));
2226
2227 /* Get the device data */
2228 sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
2229 if (sc == NULL) {
2230 /* the device is no longer valid/functioning */
2231 return ENXIO;
2232 }
2233
2234 /* Only trigger the encoder if the ring buffer is empty */
2235 if (!sc->encoding && sc->enc_pool.read == sc->enc_pool.write) {
2236 if (cxm_start_encoder(sc) < 0)
2237 return ENXIO;
2238 if (ap->a_ioflag & IO_NDELAY)
2239 return EWOULDBLOCK;
2240 }
2241
2242 buffers_available = 0;
2243
2244 crit_enter();
2245 while (sc->enc_pool.read == sc->enc_pool.write) {
2246 error = tsleep(&sc->enc_pool.read, PCATCH, "cxmrd", 0);
2247 if (error) {
2248 crit_exit();
2249 return error;
2250 }
2251 }
2252
2253 /*
2254 * Determine the number of buffers available at this * instant *
2255 * taking in consideration that the ring buffer wraps.
2256 */
2257 buffers_available = sc->enc_pool.write - sc->enc_pool.read;
2258 if (buffers_available < 0)
2259 buffers_available += CXM_SG_BUFFERS;
2260 crit_exit();
2261
2262 offset = sc->enc_pool.offset;
2263
2264 for (buffers_read = 0, i = sc->enc_pool.read;
2265 buffers_read != buffers_available && ap->a_uio->uio_resid;
2266 buffers_read++, i = (i + 1) % CXM_SG_BUFFERS) {
2267
2268 current = cxm_encoder_fixup_byte_order (sc, i, offset);
2269
2270 nbytes = sc->enc_pool.bufs[current].size - offset;
2271
2272 /* Don't transfer more than requested */
2273 if (nbytes > ap->a_uio->uio_resid)
2274 nbytes = ap->a_uio->uio_resid;
2275
2276 error = uiomove(sc->enc_pool.bufs[current].vaddr + offset,
2277 nbytes, ap->a_uio);
2278 if (error)
2279 return error;
2280
2281 offset += nbytes;
2282
2283 /* Handle a partial read of a buffer */
2284 if (!ap->a_uio->uio_resid && offset != sc->enc_pool.bufs[i].size)
2285 break;
2286
2287 offset = 0;
2288 }
2289
2290 sc->enc_pool.offset = offset;
2291
2292 /* Update the books */
2293 crit_enter();
2294 sc->enc_pool.read = (sc->enc_pool.read + buffers_read)
2295 % CXM_SG_BUFFERS;
2296 crit_exit();
2297
2298 return 0;
2299}
2300
2301
2302/*
2303 *
2304 */
2305int
2306cxm_ioctl(struct dev_ioctl_args *ap)
2307{
2308 cdev_t dev = ap->a_head.a_dev;
2309 int brightness;
2310 int chroma_saturation;
2311 int contrast;
2312 int fps;
2313 int hue;
2314 int result;
2315 int status;
2316 int unit;
2317 unsigned int i;
2318 unsigned int sig;
2319 unsigned long freq;
2320 struct cxm_softc *sc;
2321 enum cxm_source source;
2322 struct bktr_capture_area *cap;
2323 struct bktr_remote *remote;
2324
2325 unit = UNIT(minor(dev));
2326
2327 /* Get the device data */
2328 sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
2329 if (sc == NULL) {
2330 /* the device is no longer valid/functioning */
2331 return ENXIO;
2332 }
2333
2334 switch (ap->a_cmd) {
2335 case BT848_GAUDIO:
2336 switch (cxm_msp_selected_source(sc)) {
2337 case cxm_tuner_source:
2338 *(int *) ap->a_data = AUDIO_TUNER;
2339 break;
2340
2341 case cxm_line_in_source_composite:
2342 case cxm_line_in_source_svideo:
2343 *(int *) ap->a_data = AUDIO_EXTERN;
2344 break;
2345
2346 case cxm_fm_source:
2347 *(int *) ap->a_data = AUDIO_INTERN;
2348 break;
2349
2350 default:
2351 return ENXIO;
2352 }
2353
2354 if (cxm_msp_is_muted(sc) == 1)
2355 *(int *) ap->a_data |= AUDIO_MUTE;
2356 break;
2357
2358 case BT848_SAUDIO:
2359 source = cxm_unknown_source;
2360
2361 switch (*(int *) ap->a_data) {
2362 case AUDIO_TUNER:
2363 source = cxm_tuner_source;
2364 break;
2365
2366 case AUDIO_EXTERN:
2367 source = cxm_line_in_source_composite;
2368 break;
2369
2370 case AUDIO_INTERN:
2371 source = cxm_fm_source;
2372 break;
2373
2374 case AUDIO_MUTE:
2375 if (cxm_msp_mute(sc) < 0)
2376 return ENXIO;
2377 return 0;
2378
2379 case AUDIO_UNMUTE:
2380 if (cxm_msp_unmute(sc) < 0)
2381 return ENXIO;
2382 return 0;
2383
2384 default:
2385 return EINVAL;
2386 }
2387
2388 if (sc->encoding) {
2389
2390 /*
2391 * Switching between audio + video and audio only
2392 * subtypes isn't supported while encoding.
2393 */
2394
2395 if (source != sc->source
2396 && (source == cxm_fm_source
2397 || sc->source == cxm_fm_source))
2398 return EBUSY;
2399 }
2400
2401 if (cxm_pause_encoder(sc) < 0)
2402 return ENXIO;
2403
2404 if (cxm_msp_select_source(sc, source) < 0)
2405 return ENXIO;
2406
2407 if (source == cxm_fm_source)
2408 sc->source = source;
2409
2410 result = cxm_encoder_wait_for_lock(sc);
2411 if (result < 0)
2412 return ENXIO;
2413 else if (result == 0)
2414 return EINVAL;
2415
2416 if (cxm_unpause_encoder(sc) < 0)
2417 return ENXIO;
2418 break;
2419
2420 case BT848_GBRIG:
2421 brightness = cxm_saa7115_get_brightness(sc);
2422
2423 if (brightness < 0)
2424 return ENXIO;
2425
2426 /*
2427 * Brooktree brightness:
2428 * 0x80 = -50.0%, 0x00 = +0.0%, 0x7f = +49.6%
2429 */
2430 *(int *)ap->a_data = (int)(unsigned char)brightness - 128;
2431 break;
2432
2433 case BT848_SBRIG:
2434
2435 /*
2436 * Brooktree brightness:
2437 * 0x80 = -50.0%, 0x00 = +0.0%, 0x7f = +49.6%
2438 */
2439 brightness = *(int *)ap->a_data + 128;
2440
2441 if (cxm_saa7115_set_brightness(sc, brightness) < 0)
2442 return ENXIO;
2443 break;
2444
2445 case METEORGBRIG:
2446 brightness = cxm_saa7115_get_brightness(sc);
2447
2448 if (brightness < 0)
2449 return ENXIO;
2450
2451 *(unsigned char *)ap->a_data = (unsigned char)brightness;
2452 break;
2453
2454 case METEORSBRIG:
2455 brightness = *(unsigned char *)ap->a_data;
2456
2457 if (cxm_saa7115_set_brightness(sc, brightness) < 0)
2458 return ENXIO;
2459 break;
2460
2461 case BT848_GCSAT:
2462 chroma_saturation = cxm_saa7115_get_chroma_saturation(sc);
2463
2464 if (chroma_saturation < 0)
2465 return ENXIO;
2466
2467 /*
2468 * Brooktree chroma saturation:
2469 * 0x000 = 0%, 0x0fe = 100%, 0x1ff = 201.18%
2470 */
2471 *(int *)ap->a_data = ((signed char)chroma_saturation > 0)
2472 ? (chroma_saturation * 4 - 2) : 0;
2473 break;
2474
2475 case BT848_SCSAT:
2476
2477 /*
2478 * Brooktree chroma saturation:
2479 * 0x000 = 0%, 0x0fe = 100%, 0x1ff = 201.18%
2480 */
2481 chroma_saturation = (*(int *)ap->a_data & 0x1ff) < 510
2482 ? ((*(int *)ap->a_data & 0x1ff) + 2) / 4 : 127;
2483
2484 if (cxm_saa7115_set_chroma_saturation(sc, chroma_saturation)
2485 < 0)
2486 return ENXIO;
2487
2488 break;
2489
2490 case METEORGCSAT:
2491 chroma_saturation = cxm_saa7115_get_chroma_saturation(sc);
2492
2493 if (chroma_saturation < 0)
2494 return ENXIO;
2495
2496 *(unsigned char *)ap->a_data = (unsigned char)chroma_saturation;
2497 break;
2498
2499 case METEORSCSAT:
2500 chroma_saturation = *(unsigned char *)ap->a_data;
2501
2502 if (cxm_saa7115_set_chroma_saturation(sc, chroma_saturation)
2503 < 0)
2504 return ENXIO;
2505 break;
2506
2507 case METEORGCONT:
2508 contrast = cxm_saa7115_get_contrast(sc);
2509
2510 if (contrast < 0)
2511 return ENXIO;
2512
2513 *(unsigned char *)ap->a_data = (unsigned char)contrast;
2514 break;
2515
2516 case METEORSCONT:
2517 contrast = *(unsigned char *)ap->a_data;
2518
2519 if (cxm_saa7115_set_contrast(sc, contrast) < 0)
2520 return ENXIO;
2521 break;
2522
2523 case BT848_GHUE:
2524 hue = cxm_saa7115_get_hue(sc);
2525
2526 if (hue < 0)
2527 return ENXIO;
2528
2529 *(int *)ap->a_data = (signed char)hue;
2530 break;
2531
2532 case BT848_SHUE:
2533 hue = *(int *)ap->a_data;
2534
2535 if (cxm_saa7115_set_hue(sc, hue) < 0)
2536 return ENXIO;
2537 break;
2538
2539 case METEORGHUE:
2540 hue = cxm_saa7115_get_hue(sc);
2541
2542 if (hue < 0)
2543 return ENXIO;
2544
2545 *(signed char *)ap->a_data = (signed char)hue;
2546 break;
2547
2548 case METEORSHUE:
2549 hue = *(signed char *)ap->a_data;
2550
2551 if (cxm_saa7115_set_hue(sc, hue) < 0)
2552 return ENXIO;
2553 break;
2554
2555 case METEORCAPTUR:
2556 switch (*(int *) ap->a_data) {
2557 case METEOR_CAP_CONTINOUS:
2558 if (cxm_start_encoder(sc) < 0)
2559 return ENXIO;
2560 break;
2561
2562 case METEOR_CAP_STOP_CONT:
2563 if (cxm_stop_encoder(sc) < 0)
2564 return ENXIO;
2565 break;
2566
2567 default:
2568 return EINVAL;
2569 }
2570 break;
2571
2572 case BT848_GCAPAREA:
2573 cap = (struct bktr_capture_area *)ap->a_data;
2574 memset (cap, 0, sizeof (*cap));
2575 cap->x_offset = 0;
2576 cap->y_offset = 0;
2577 cap->x_size = sc->profile->width;
2578 cap->y_size = sc->profile->height;
2579 break;
2580
2581 case BT848_SCAPAREA:
2582 if (sc->encoding)
2583 return EBUSY;
2584
2585 cap = (struct bktr_capture_area *)ap->a_data;
2586 if (cap->x_offset || cap->y_offset
2587 || (cap->x_size % CXM_MACROBLOCK_WIDTH)
2588 || (cap->y_size % CXM_MACROBLOCK_HEIGHT))
2589 return EINVAL;
2590
2591 /*
2592 * Setting the width and height has the side effect of
2593 * chosing between the VCD, SVCD, and DVD profiles.
2594 */
2595
2596 for (i = 0; i < NUM_ELEMENTS(codec_profiles); i++)
2597 if (codec_profiles[i]->width == cap->x_size
2598 && codec_profiles[i]->height == cap->y_size)
2599 break;
2600
2601 if (i >= NUM_ELEMENTS(codec_profiles))
2602 return EINVAL;
2603
2604 sc->profile = codec_profiles[i];
2605 break;
2606
2607 case BT848GFMT:
2608 switch (cxm_saa7115_detected_format(sc)) {
2609 case cxm_ntsc_60hz_source_format:
2610 *(unsigned long *)ap->a_data = BT848_IFORM_F_NTSCM;
2611 break;
2612
2613 case cxm_pal_50hz_source_format:
2614 *(unsigned long *)ap->a_data = BT848_IFORM_F_PALBDGHI;
2615 break;
2616
2617 case cxm_secam_50hz_source_format:
2618 *(unsigned long *)ap->a_data = BT848_IFORM_F_SECAM;
2619 break;
2620
2621 case cxm_pal_60hz_source_format:
2622 *(unsigned long *)ap->a_data = BT848_IFORM_F_PALM;
2623 break;
2624
2625 case cxm_bw_50hz_source_format:
2626 case cxm_bw_60hz_source_format:
2627 case cxm_ntsc_50hz_source_format:
2628 *(unsigned long *)ap->a_data = BT848_IFORM_F_AUTO;
2629 break;
2630
2631 default:
2632 return ENXIO;
2633 }
2634 break;
2635
2636 case METEORGFMT:
2637 switch (cxm_saa7115_detected_format(sc)) {
2638 case cxm_ntsc_60hz_source_format:
2639 *(unsigned long *)ap->a_data = METEOR_FMT_NTSC;
2640 break;
2641
2642 case cxm_pal_50hz_source_format:
2643 *(unsigned long *)ap->a_data = METEOR_FMT_PAL;
2644 break;
2645
2646 case cxm_secam_50hz_source_format:
2647 *(unsigned long *)ap->a_data = METEOR_FMT_SECAM;
2648 break;
2649
2650 case cxm_bw_50hz_source_format:
2651 case cxm_bw_60hz_source_format:
2652 case cxm_ntsc_50hz_source_format:
2653 case cxm_pal_60hz_source_format:
2654 *(unsigned long *)ap->a_data = METEOR_FMT_AUTOMODE;
2655 break;
2656
2657 default:
2658 return ENXIO;
2659 }
2660 break;
2661
2662 case METEORGFPS:
2663 fps = cxm_saa7115_detected_fps(sc);
2664
2665 if (fps < 0)
2666 return ENXIO;
2667
2668 *(unsigned short *)ap->a_data = fps;
2669 break;
2670
2671 case METEORGINPUT:
2672 switch (sc->source) {
2673 case cxm_tuner_source:
2674 *(unsigned long *)ap->a_data = METEOR_INPUT_DEV1;
2675 break;
2676
2677 case cxm_line_in_source_composite:
2678 *(unsigned long *)ap->a_data = METEOR_INPUT_DEV2;
2679 break;
2680
2681 case cxm_line_in_source_svideo:
2682 *(unsigned long *)ap->a_data = METEOR_INPUT_DEV_SVIDEO;
2683 break;
2684
2685 default:
2686 return ENXIO;
2687 }
2688 break;
2689
2690 case METEORSINPUT:
2691 source = cxm_unknown_source;
2692
2693 switch (*(unsigned long *)ap->a_data & 0xf000) {
2694 case METEOR_INPUT_DEV1:
2695 source = cxm_tuner_source;
2696 break;
2697
2698 case METEOR_INPUT_DEV2:
2699 source = cxm_line_in_source_composite;
2700 break;
2701
2702 case METEOR_INPUT_DEV_SVIDEO:
2703 source = cxm_line_in_source_svideo;
2704 break;
2705
2706 default:
2707 return EINVAL;
2708 }
2709
2710 if (sc->encoding) {
2711
2712 /*
2713 * Switching between audio + video and audio only
2714 * subtypes isn't supported while encoding.
2715 */
2716
2717 if (source != sc->source
2718 && (source == cxm_fm_source
2719 || sc->source == cxm_fm_source))
2720 return EBUSY;
2721 }
2722
2723 if (cxm_pause_encoder(sc) < 0)
2724 return ENXIO;
2725
2726 if (cxm_saa7115_select_source(sc, source) < 0)
2727 return ENXIO;
2728 if (cxm_msp_select_source(sc, source) < 0)
2729 return ENXIO;
2730 sc->source = source;
2731
2732 result = cxm_encoder_wait_for_lock(sc);
2733 if (result < 0)
2734 return ENXIO;
2735 else if (result == 0)
2736 return EINVAL;
2737
2738 if (cxm_unpause_encoder(sc) < 0)
2739 return ENXIO;
2740 break;
2741
2742 case METEORGSIGNAL:
2743 *(unsigned int *)ap->a_data = sc->enc_signal;
2744 break;
2745
2746 case METEORSSIGNAL:
2747 sig = *(unsigned int *)ap->a_data;
2748
2749 if (!_SIG_VALID(sig))
2750 return EINVAL;
2751
2752 /*
2753 * Historically, applications used METEOR_SIG_MODE_MASK
2754 * to reset signal delivery.
2755 */
2756 if (sig == METEOR_SIG_MODE_MASK)
2757 sig = 0;
2758
2759 crit_enter();
2760 sc->enc_proc = sig ? curproc : NULL;
2761 sc->enc_signal = sig;
2762 crit_exit();
2763 break;
2764
2765 case RADIO_GETFREQ:
2766 /* Convert from kHz to MHz * 100 */
2767 freq = sc->tuner_freq / 10;
2768
2769 *(unsigned int *)ap->a_data = freq;
2770 break;
2771
2772 case RADIO_SETFREQ:
2773 if (sc->source == cxm_fm_source)
2774 if (cxm_pause_encoder(sc) < 0)
2775 return ENXIO;
2776
2777 /* Convert from MHz * 100 to kHz */
2778 freq = *(unsigned int *)ap->a_data * 10;
2779
2780 if (cxm_tuner_select_frequency(sc, cxm_tuner_fm_freq_type,
2781 freq) < 0)
2782 return ENXIO;
2783
2784 /*
2785 * Explicitly wait for the tuner lock so we
2786 * can indicate if there's a station present.
2787 */
2788 if (cxm_tuner_wait_for_lock(sc) < 0)
2789 return EINVAL;
2790
2791 result = cxm_encoder_wait_for_lock(sc);
2792 if (result < 0)
2793 return ENXIO;
2794 else if (result == 0)
2795 return EINVAL;
2796
2797 if (sc->source == cxm_fm_source)
2798 if (cxm_unpause_encoder(sc) < 0)
2799 return ENXIO;
2800 break;
2801
2802 case TVTUNER_GETAFC:
2803 *(int *)ap->a_data = sc->tuner_afc;
2804 break;
2805
2806 case TVTUNER_SETAFC:
2807 sc->tuner_afc = (*(int *)ap->a_data != 0);
2808 break;
2809
2810 case TVTUNER_GETTYPE:
2811 *(unsigned int *)ap->a_data = cxm_tuner_selected_channel_set(sc);
2812 break;
2813
2814 case TVTUNER_SETTYPE:
2815 if (cxm_tuner_select_channel_set(sc, *(unsigned int *)ap->a_data) < 0)
2816 return EINVAL;
2817 break;
2818
2819 case TVTUNER_SETCHNL:
2820 if (sc->source == cxm_tuner_source)
2821 if (cxm_pause_encoder(sc) < 0)
2822 return ENXIO;
2823
2824 if (cxm_tuner_select_channel(sc, *(unsigned int *)ap->a_data) < 0)
2825 return ENXIO;
2826
2827 if (sc->tuner_afc)
2828 if (cxm_tuner_apply_afc(sc) < 0)
2829 return EINVAL;
2830
2831 /*
2832 * Explicitly wait for the tuner lock so we
2833 * can indicate if there's a station present.
2834 */
2835 if (cxm_tuner_wait_for_lock(sc) < 0)
2836 return EINVAL;
2837
2838 result = cxm_encoder_wait_for_lock(sc);
2839 if (result < 0)
2840 return ENXIO;
2841 else if (result == 0)
2842 return EINVAL;
2843
2844 if (sc->source == cxm_tuner_source)
2845 if (cxm_unpause_encoder(sc) < 0)
2846 return ENXIO;
2847 break;
2848
2849 case TVTUNER_GETFREQ:
2850 /* Convert from kHz to MHz * 16 */
2851 freq = (sc->tuner_freq * 16) / 1000;
2852
2853 *(unsigned int *)ap->a_data = freq;
2854 break;
2855
2856 case TVTUNER_SETFREQ:
2857 if (sc->source == cxm_tuner_source)
2858 if (cxm_pause_encoder(sc) < 0)
2859 return ENXIO;
2860
2861 /* Convert from MHz * 16 to kHz */
2862 freq = (*(unsigned int *)ap->a_data * 1000) / 16;
2863
2864 if (cxm_tuner_select_frequency(sc, cxm_tuner_tv_freq_type,
2865 freq) < 0)
2866 return ENXIO;
2867
2868 /*
2869 * Explicitly wait for the tuner lock so we
2870 * can indicate if there's a station present.
2871 */
2872 if (cxm_tuner_wait_for_lock(sc) < 0)
2873 return EINVAL;
2874
2875 result = cxm_encoder_wait_for_lock(sc);
2876 if (result < 0)
2877 return ENXIO;
2878 else if (result == 0)
2879 return EINVAL;
2880
2881 if (sc->source == cxm_tuner_source)
2882 if (cxm_unpause_encoder(sc) < 0)
2883 return ENXIO;
2884
2885 break;
2886
2887 case TVTUNER_GETSTATUS:
2888 status = cxm_tuner_status(sc);
2889 if (status < 0)
2890 return ENXIO;
2891 *(unsigned long *)ap->a_data = status & 0xff;
2892 break;
2893
2894 case REMOTE_GETKEY:
2895 remote = (struct bktr_remote *)ap->a_data;
2896 if (cxm_ir_key(sc, (char *)remote, sizeof(*remote)) < 0)
2897 return ENXIO;
2898 break;
2899
2900 default:
2901 return ENOTTY;
2902 }
2903
2904 return 0;
2905}
2906
2907
2908int
2909cxm_poll(struct dev_poll_args *ap)
2910{
2911 cdev_t dev = ap->a_head.a_dev;
2912 int revents;
2913 int unit;
2914 struct cxm_softc *sc;
2915
2916 unit = UNIT(minor(dev));
2917
2918 /* Get the device data */
2919 sc = (struct cxm_softc*)devclass_get_softc(cxm_devclass, unit);
2920 if (sc == NULL) {
2921 /* the device is no longer valid/functioning */
2922 return POLLHUP;
2923 }
2924
2925 revents = 0;
2926
2927 crit_enter();
2928 if (ap->a_events & (POLLIN | POLLRDNORM)) {
2929 if (sc->enc_pool.read == sc->enc_pool.write)
2930 selrecord(curthread, &sc->enc_sel);
2931 else
2932 revents = ap->a_events & (POLLIN | POLLRDNORM);
2933 }
2934 crit_exit();
2935
2936 return revents;
2937}