Commit 7b8880140ff6aec6a5bec7929b03ce0b96a7c79a
Committed by
Mauro Carvalho Chehab
1 parent
c771261330
Exists in
master
and in
4 other branches
V4L/DVB (7007): cx23885: Add basic video support for the HVR1800
This enabled basic preview NTSC and PAL support for the HVR1800. Signed-off-by: Steven Toth <stoth@hauppauge.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Showing 6 changed files with 366 additions and 42 deletions Side-by-side Diff
drivers/media/video/cx23885/Makefile
drivers/media/video/cx23885/cx23885-cards.c
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | #include <linux/module.h> |
24 | 24 | #include <linux/pci.h> |
25 | 25 | #include <linux/delay.h> |
26 | +#include <media/cx25840.h> | |
26 | 27 | |
27 | 28 | #include "cx23885.h" |
28 | 29 | |
29 | 30 | |
30 | 31 | |
31 | 32 | |
32 | 33 | |
33 | 34 | |
... | ... | @@ -71,23 +72,29 @@ |
71 | 72 | }, |
72 | 73 | [CX23885_BOARD_HAUPPAUGE_HVR1800] = { |
73 | 74 | .name = "Hauppauge WinTV-HVR1800", |
75 | + .porta = CX23885_ANALOG_VIDEO, | |
74 | 76 | .portc = CX23885_MPEG_DVB, |
77 | + .tuner_type = TUNER_PHILIPS_TDA8290, | |
78 | + .tuner_addr = 0x42, /* 0x84 >> 1 */ | |
75 | 79 | .input = {{ |
76 | 80 | .type = CX23885_VMUX_TELEVISION, |
77 | - .vmux = 0, | |
78 | - .gpio0 = 0xff00, | |
81 | + .vmux = CX25840_VIN7_CH3 | | |
82 | + CX25840_VIN5_CH2 | | |
83 | + CX25840_VIN2_CH1, | |
84 | + .gpio0 = 0, | |
79 | 85 | },{ |
80 | - .type = CX23885_VMUX_DEBUG, | |
81 | - .vmux = 0, | |
82 | - .gpio0 = 0xff01, | |
83 | - },{ | |
84 | 86 | .type = CX23885_VMUX_COMPOSITE1, |
85 | - .vmux = 1, | |
86 | - .gpio0 = 0xff02, | |
87 | + .vmux = CX25840_VIN7_CH3 | | |
88 | + CX25840_VIN4_CH2 | | |
89 | + CX25840_VIN6_CH1, | |
90 | + .gpio0 = 0, | |
87 | 91 | },{ |
88 | 92 | .type = CX23885_VMUX_SVIDEO, |
89 | - .vmux = 2, | |
90 | - .gpio0 = 0xff02, | |
93 | + .vmux = CX25840_VIN7_CH3 | | |
94 | + CX25840_VIN4_CH2 | | |
95 | + CX25840_VIN8_CH1 | | |
96 | + CX25840_SVIDEO_ON, | |
97 | + .gpio0 = 0, | |
91 | 98 | }}, |
92 | 99 | }, |
93 | 100 | [CX23885_BOARD_HAUPPAUGE_HVR1250] = { |
drivers/media/video/cx23885/cx23885-core.c
... | ... | @@ -50,7 +50,7 @@ |
50 | 50 | static unsigned int cx23885_devcount; |
51 | 51 | |
52 | 52 | static DEFINE_MUTEX(devlist); |
53 | -static LIST_HEAD(cx23885_devlist); | |
53 | +LIST_HEAD(cx23885_devlist); | |
54 | 54 | |
55 | 55 | #define NO_SYNC_LINE (-1U) |
56 | 56 | |
... | ... | @@ -356,7 +356,7 @@ |
356 | 356 | return incr[risc >> 28] ? incr[risc >> 28] : 1; |
357 | 357 | } |
358 | 358 | |
359 | -static void cx23885_wakeup(struct cx23885_tsport *port, | |
359 | +void cx23885_wakeup(struct cx23885_tsport *port, | |
360 | 360 | struct cx23885_dmaqueue *q, u32 count) |
361 | 361 | { |
362 | 362 | struct cx23885_dev *dev = port->dev; |
... | ... | @@ -392,7 +392,7 @@ |
392 | 392 | __FUNCTION__, bc); |
393 | 393 | } |
394 | 394 | |
395 | -static int cx23885_sram_channel_setup(struct cx23885_dev *dev, | |
395 | +int cx23885_sram_channel_setup(struct cx23885_dev *dev, | |
396 | 396 | struct sram_channel *ch, |
397 | 397 | unsigned int bpl, u32 risc) |
398 | 398 | { |
... | ... | @@ -465,7 +465,7 @@ |
465 | 465 | return 0; |
466 | 466 | } |
467 | 467 | |
468 | -static void cx23885_sram_channel_dump(struct cx23885_dev *dev, | |
468 | +void cx23885_sram_channel_dump(struct cx23885_dev *dev, | |
469 | 469 | struct sram_channel *ch) |
470 | 470 | { |
471 | 471 | static char *name[] = { |
... | ... | @@ -592,15 +592,18 @@ |
592 | 592 | |
593 | 593 | mdelay(100); |
594 | 594 | |
595 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH01 ], 188*4, 0); | |
596 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH02 ], 128, 0); | |
597 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH03 ], 188*4, 0); | |
598 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH04 ], 128, 0); | |
599 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH05 ], 128, 0); | |
600 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH06 ], 188*4, 0); | |
601 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH07 ], 128, 0); | |
602 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH08 ], 128, 0); | |
603 | - cx23885_sram_channel_setup(dev, &dev->sram_channels[ SRAM_CH09 ], 128, 0); | |
595 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01], | |
596 | + 720*4, 0); | |
597 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0); | |
598 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03], | |
599 | + 188*4, 0); | |
600 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0); | |
601 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0); | |
602 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06], | |
603 | + 188*4, 0); | |
604 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0); | |
605 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0); | |
606 | + cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0); | |
604 | 607 | |
605 | 608 | cx23885_gpio_setup(dev); |
606 | 609 | } |
... | ... | @@ -634,7 +637,7 @@ |
634 | 637 | } |
635 | 638 | |
636 | 639 | static void cx23885_timeout(unsigned long data); |
637 | -static int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | |
640 | +int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | |
638 | 641 | u32 reg, u32 mask, u32 value); |
639 | 642 | |
640 | 643 | static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *port, int portno) |
... | ... | @@ -854,6 +857,17 @@ |
854 | 857 | |
855 | 858 | cx23885_pci_quirks(dev); |
856 | 859 | |
860 | + /* Assume some sensible defaults */ | |
861 | + dev->tuner_type = cx23885_boards[dev->board].tuner_type; | |
862 | + dev->tuner_addr = cx23885_boards[dev->board].tuner_addr; | |
863 | + dev->radio_type = cx23885_boards[dev->board].radio_type; | |
864 | + dev->radio_addr = cx23885_boards[dev->board].radio_addr; | |
865 | + | |
866 | + dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n", | |
867 | + __FUNCTION__, dev->tuner_type, dev->tuner_addr); | |
868 | + dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n", | |
869 | + __FUNCTION__, dev->radio_type, dev->radio_addr); | |
870 | + | |
857 | 871 | /* init hardware */ |
858 | 872 | cx23885_reset(dev); |
859 | 873 | |
860 | 874 | |
... | ... | @@ -864,14 +878,21 @@ |
864 | 878 | cx23885_card_setup(dev); |
865 | 879 | cx23885_ir_init(dev); |
866 | 880 | |
867 | - if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { | |
881 | + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) { | |
882 | + if (cx23885_video_register(dev) < 0) { | |
883 | + printk(KERN_ERR "%s() Failed to register analog " | |
884 | + "video adapters on VID_A\n", __FUNCTION__); | |
885 | + } | |
886 | + } | |
887 | + | |
888 | + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) { | |
868 | 889 | if (cx23885_dvb_register(&dev->ts1) < 0) { |
869 | 890 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", |
870 | 891 | __FUNCTION__); |
871 | 892 | } |
872 | 893 | } |
873 | 894 | |
874 | - if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { | |
895 | + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { | |
875 | 896 | if (cx23885_dvb_register(&dev->ts2) < 0) { |
876 | 897 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", |
877 | 898 | __FUNCTION__); |
... | ... | @@ -891,6 +912,9 @@ |
891 | 912 | if (!atomic_dec_and_test(&dev->refcount)) |
892 | 913 | return; |
893 | 914 | |
915 | + if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) | |
916 | + cx23885_video_unregister(dev); | |
917 | + | |
894 | 918 | if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) |
895 | 919 | cx23885_dvb_unregister(&dev->ts1); |
896 | 920 | |
897 | 921 | |
... | ... | @@ -958,7 +982,46 @@ |
958 | 982 | return rp; |
959 | 983 | } |
960 | 984 | |
985 | +int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |
986 | + struct scatterlist *sglist, unsigned int top_offset, | |
987 | + unsigned int bottom_offset, unsigned int bpl, | |
988 | + unsigned int padding, unsigned int lines) | |
989 | +{ | |
990 | + u32 instructions, fields; | |
991 | + u32 *rp; | |
992 | + int rc; | |
961 | 993 | |
994 | + fields = 0; | |
995 | + if (UNSET != top_offset) | |
996 | + fields++; | |
997 | + if (UNSET != bottom_offset) | |
998 | + fields++; | |
999 | + | |
1000 | + /* estimate risc mem: worst case is one write per page border + | |
1001 | + one write per scan line + syncs + jump (all 2 dwords). Padding | |
1002 | + can cause next bpl to start close to a page border. First DMA | |
1003 | + region may be smaller than PAGE_SIZE */ | |
1004 | + /* write and jump need and extra dword */ | |
1005 | + instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); | |
1006 | + instructions += 2; | |
1007 | + if ((rc = btcx_riscmem_alloc(pci,risc,instructions*12)) < 0) | |
1008 | + return rc; | |
1009 | + | |
1010 | + /* write risc instructions */ | |
1011 | + rp = risc->cpu; | |
1012 | + if (UNSET != top_offset) | |
1013 | + rp = cx23885_risc_field(rp, sglist, top_offset, 0, | |
1014 | + bpl, padding, lines); | |
1015 | + if (UNSET != bottom_offset) | |
1016 | + rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200, | |
1017 | + bpl, padding, lines); | |
1018 | + | |
1019 | + /* save pointer to jmp instruction address */ | |
1020 | + risc->jmp = rp; | |
1021 | + BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size); | |
1022 | + return 0; | |
1023 | +} | |
1024 | + | |
962 | 1025 | static int cx23885_risc_databuffer(struct pci_dev *pci, |
963 | 1026 | struct btcx_riscmem *risc, |
964 | 1027 | struct scatterlist *sglist, |
... | ... | @@ -990,7 +1053,7 @@ |
990 | 1053 | return 0; |
991 | 1054 | } |
992 | 1055 | |
993 | -static int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | |
1056 | +int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | |
994 | 1057 | u32 reg, u32 mask, u32 value) |
995 | 1058 | { |
996 | 1059 | u32 *rp; |
... | ... | @@ -1023,6 +1086,57 @@ |
1023 | 1086 | buf->vb.state = VIDEOBUF_NEEDS_INIT; |
1024 | 1087 | } |
1025 | 1088 | |
1089 | +static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) | |
1090 | +{ | |
1091 | + struct cx23885_dev *dev = port->dev; | |
1092 | + | |
1093 | + dprintk(1, "%s() Register Dump\n", __FUNCTION__); | |
1094 | + dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __FUNCTION__, | |
1095 | + cx_read(DEV_CNTRL2)); | |
1096 | + dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __FUNCTION__, | |
1097 | + cx_read(PCI_INT_MSK)); | |
1098 | + dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __FUNCTION__, | |
1099 | + cx_read(AUDIO_INT_INT_MSK)); | |
1100 | + dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __FUNCTION__, | |
1101 | + cx_read(AUD_INT_DMA_CTL)); | |
1102 | + dprintk(1, "%s() AUD_EXT_INT_MSK 0x%08X\n", __FUNCTION__, | |
1103 | + cx_read(AUDIO_EXT_INT_MSK)); | |
1104 | + dprintk(1, "%s() AUD_EXT_DMA_CTL 0x%08X\n", __FUNCTION__, | |
1105 | + cx_read(AUD_EXT_DMA_CTL)); | |
1106 | + dprintk(1, "%s() PAD_CTRL 0x%08X\n", __FUNCTION__, | |
1107 | + cx_read(PAD_CTRL)); | |
1108 | + dprintk(1, "%s() ALT_PIN_OUT_SEL 0x%08X\n", __FUNCTION__, | |
1109 | + cx_read(ALT_PIN_OUT_SEL)); | |
1110 | + dprintk(1, "%s() GPIO2 0x%08X\n", __FUNCTION__, | |
1111 | + cx_read(GPIO2)); | |
1112 | + dprintk(1, "%s() gpcnt(0x%08X) 0x%08X\n", __FUNCTION__, | |
1113 | + port->reg_gpcnt, cx_read(port->reg_gpcnt)); | |
1114 | + dprintk(1, "%s() gpcnt_ctl(0x%08X) 0x%08x\n", __FUNCTION__, | |
1115 | + port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl)); | |
1116 | + dprintk(1, "%s() dma_ctl(0x%08X) 0x%08x\n", __FUNCTION__, | |
1117 | + port->reg_dma_ctl, cx_read(port->reg_dma_ctl)); | |
1118 | + dprintk(1, "%s() src_sel(0x%08X) 0x%08x\n", __FUNCTION__, | |
1119 | + port->reg_src_sel, cx_read(port->reg_src_sel)); | |
1120 | + dprintk(1, "%s() lngth(0x%08X) 0x%08x\n", __FUNCTION__, | |
1121 | + port->reg_lngth, cx_read(port->reg_lngth)); | |
1122 | + dprintk(1, "%s() hw_sop_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, | |
1123 | + port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl)); | |
1124 | + dprintk(1, "%s() gen_ctrl(0x%08X) 0x%08x\n", __FUNCTION__, | |
1125 | + port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl)); | |
1126 | + dprintk(1, "%s() bd_pkt_status(0x%08X) 0x%08x\n", __FUNCTION__, | |
1127 | + port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status)); | |
1128 | + dprintk(1, "%s() sop_status(0x%08X) 0x%08x\n", __FUNCTION__, | |
1129 | + port->reg_sop_status, cx_read(port->reg_sop_status)); | |
1130 | + dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __FUNCTION__, | |
1131 | + port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat)); | |
1132 | + dprintk(1, "%s() vld_misc(0x%08X) 0x%08x\n", __FUNCTION__, | |
1133 | + port->reg_vld_misc, cx_read(port->reg_vld_misc)); | |
1134 | + dprintk(1, "%s() ts_clk_en(0x%08X) 0x%08x\n", __FUNCTION__, | |
1135 | + port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en)); | |
1136 | + dprintk(1, "%s() ts_int_msk(0x%08X) 0x%08x\n", __FUNCTION__, | |
1137 | + port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk)); | |
1138 | +} | |
1139 | + | |
1026 | 1140 | static int cx23885_start_dma(struct cx23885_tsport *port, |
1027 | 1141 | struct cx23885_dmaqueue *q, |
1028 | 1142 | struct cx23885_buffer *buf) |
... | ... | @@ -1085,6 +1199,9 @@ |
1085 | 1199 | |
1086 | 1200 | cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */ |
1087 | 1201 | |
1202 | + if (debug > 4) | |
1203 | + cx23885_tsport_reg_dump(port); | |
1204 | + | |
1088 | 1205 | return 0; |
1089 | 1206 | } |
1090 | 1207 | |
... | ... | @@ -1100,7 +1217,7 @@ |
1100 | 1217 | return 0; |
1101 | 1218 | } |
1102 | 1219 | |
1103 | -static int cx23885_restart_queue(struct cx23885_tsport *port, | |
1220 | +int cx23885_restart_queue(struct cx23885_tsport *port, | |
1104 | 1221 | struct cx23885_dmaqueue *q) |
1105 | 1222 | { |
1106 | 1223 | struct cx23885_dev *dev = port->dev; |
1107 | 1224 | |
1108 | 1225 | |
... | ... | @@ -1324,12 +1441,15 @@ |
1324 | 1441 | struct cx23885_tsport *ts1 = &dev->ts1; |
1325 | 1442 | struct cx23885_tsport *ts2 = &dev->ts2; |
1326 | 1443 | u32 pci_status, pci_mask; |
1444 | + u32 vida_status, vida_mask; | |
1327 | 1445 | u32 ts1_status, ts1_mask; |
1328 | 1446 | u32 ts2_status, ts2_mask; |
1329 | - int ts1_count = 0, ts2_count = 0, handled = 0; | |
1447 | + int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; | |
1330 | 1448 | |
1331 | 1449 | pci_status = cx_read(PCI_INT_STAT); |
1332 | 1450 | pci_mask = cx_read(PCI_INT_MSK); |
1451 | + vida_status = cx_read(VID_A_INT_STAT); | |
1452 | + vida_mask = cx_read(VID_A_INT_MSK); | |
1333 | 1453 | ts1_status = cx_read(VID_B_INT_STAT); |
1334 | 1454 | ts1_mask = cx_read(VID_B_INT_MSK); |
1335 | 1455 | ts2_status = cx_read(VID_C_INT_STAT); |
1336 | 1456 | |
... | ... | @@ -1338,11 +1458,17 @@ |
1338 | 1458 | if ( (pci_status == 0) && (ts2_status == 0) && (ts1_status == 0) ) |
1339 | 1459 | goto out; |
1340 | 1460 | |
1461 | + vida_count = cx_read(VID_A_GPCNT); | |
1341 | 1462 | ts1_count = cx_read(ts1->reg_gpcnt); |
1342 | 1463 | ts2_count = cx_read(ts2->reg_gpcnt); |
1343 | - dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", pci_status, pci_mask ); | |
1344 | - dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", ts1_status, ts1_mask, ts1_count ); | |
1345 | - dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", ts2_status, ts2_mask, ts2_count ); | |
1464 | + dprintk(7, "pci_status: 0x%08x pci_mask: 0x%08x\n", | |
1465 | + pci_status, pci_mask); | |
1466 | + dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n", | |
1467 | + vida_status, vida_mask, vida_count); | |
1468 | + dprintk(7, "ts1_status: 0x%08x ts1_mask: 0x%08x count: 0x%x\n", | |
1469 | + ts1_status, ts1_mask, ts1_count); | |
1470 | + dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n", | |
1471 | + ts2_status, ts2_mask, ts2_count); | |
1346 | 1472 | |
1347 | 1473 | if ( (pci_status & PCI_MSK_RISC_RD) || |
1348 | 1474 | (pci_status & PCI_MSK_RISC_WR) || |
1349 | 1475 | |
... | ... | @@ -1379,11 +1505,18 @@ |
1379 | 1505 | |
1380 | 1506 | } |
1381 | 1507 | |
1382 | - if (ts1_status) | |
1383 | - handled += cx23885_irq_ts(ts1, ts1_status); | |
1508 | + if (ts1_status) { | |
1509 | + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) | |
1510 | + handled += cx23885_irq_ts(ts1, ts1_status); | |
1511 | + } | |
1384 | 1512 | |
1385 | - if (ts2_status) | |
1386 | - handled += cx23885_irq_ts(ts2, ts2_status); | |
1513 | + if (ts2_status) { | |
1514 | + if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | |
1515 | + handled += cx23885_irq_ts(ts2, ts2_status); | |
1516 | + } | |
1517 | + | |
1518 | + if (vida_status) | |
1519 | + handled += cx23885_video_irq(dev, vida_status); | |
1387 | 1520 | |
1388 | 1521 | if (handled) |
1389 | 1522 | cx_write(PCI_INT_STAT, pci_status); |
drivers/media/video/cx23885/cx23885-i2c.c
... | ... | @@ -270,7 +270,9 @@ |
270 | 270 | |
271 | 271 | static int attach_inform(struct i2c_client *client) |
272 | 272 | { |
273 | - struct cx23885_dev *dev = i2c_get_adapdata(client->adapter); | |
273 | + struct cx23885_i2c *bus = i2c_get_adapdata(client->adapter); | |
274 | + struct cx23885_dev *dev = bus->dev; | |
275 | + struct tuner_setup tun_setup; | |
274 | 276 | |
275 | 277 | dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", |
276 | 278 | client->driver->driver.name, client->addr, client->name); |
... | ... | @@ -278,6 +280,31 @@ |
278 | 280 | if (!client->driver->command) |
279 | 281 | return 0; |
280 | 282 | |
283 | + if (dev->tuner_type != UNSET) { | |
284 | + | |
285 | + dprintk(1, "%s (tuner) i2c attach [addr=0x%x,client=%s]\n", | |
286 | + client->driver->driver.name, client->addr, | |
287 | + client->name); | |
288 | + | |
289 | + if ((dev->tuner_addr == ADDR_UNSET) || | |
290 | + (dev->tuner_addr == client->addr)) { | |
291 | + | |
292 | + dprintk(1, "%s (tuner || addr UNSET)\n", | |
293 | + client->driver->driver.name); | |
294 | + | |
295 | + dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", | |
296 | + client->driver->driver.name, | |
297 | + client->addr, client->name); | |
298 | + | |
299 | + tun_setup.mode_mask = T_ANALOG_TV; | |
300 | + tun_setup.type = dev->tuner_type; | |
301 | + tun_setup.addr = dev->tuner_addr; | |
302 | + | |
303 | + client->driver->command(client, TUNER_SET_TYPE_ADDR, | |
304 | + &tun_setup); | |
305 | + } | |
306 | + } | |
307 | + | |
281 | 308 | return 0; |
282 | 309 | } |
283 | 310 | |
... | ... | @@ -316,6 +343,7 @@ |
316 | 343 | .owner = THIS_MODULE, |
317 | 344 | .id = I2C_HW_B_CX23885, |
318 | 345 | .algo = &cx23885_i2c_algo_template, |
346 | + .class = I2C_CLASS_TV_ANALOG, | |
319 | 347 | .client_register = attach_inform, |
320 | 348 | .client_unregister = detach_inform, |
321 | 349 | }; |
... | ... | @@ -371,6 +399,7 @@ |
371 | 399 | |
372 | 400 | bus->i2c_algo.data = bus; |
373 | 401 | bus->i2c_adap.algo_data = bus; |
402 | + i2c_set_adapdata(&bus->i2c_adap, bus); | |
374 | 403 | i2c_add_adapter(&bus->i2c_adap); |
375 | 404 | |
376 | 405 | bus->i2c_client.adapter = &bus->i2c_adap; |
drivers/media/video/cx23885/cx23885-reg.h
... | ... | @@ -233,6 +233,17 @@ |
233 | 233 | #define VID_A_INT_SSTAT 0x0004002C |
234 | 234 | |
235 | 235 | #define VID_B_INT_MSK 0x00040030 |
236 | +#define VID_B_MSK_BAD_PKT (1 << 20) | |
237 | +#define VID_B_MSK_VBI_OPC_ERR (1 << 17) | |
238 | +#define VID_B_MSK_OPC_ERR (1 << 16) | |
239 | +#define VID_B_MSK_VBI_SYNC (1 << 13) | |
240 | +#define VID_B_MSK_SYNC (1 << 12) | |
241 | +#define VID_B_MSK_VBI_OF (1 << 9) | |
242 | +#define VID_B_MSK_OF (1 << 8) | |
243 | +#define VID_B_MSK_VBI_RISCI2 (1 << 5) | |
244 | +#define VID_B_MSK_RISCI2 (1 << 4) | |
245 | +#define VID_B_MSK_VBI_RISCI1 (1 << 1) | |
246 | +#define VID_B_MSK_RISCI1 1 | |
236 | 247 | #define VID_B_INT_STAT 0x00040034 |
237 | 248 | #define VID_B_INT_MSTAT 0x00040038 |
238 | 249 | #define VID_B_INT_SSTAT 0x0004003C |
... | ... | @@ -336,6 +347,7 @@ |
336 | 347 | /* GPIO (417 Microsoftcontroller) Output Enable, Low Active */ |
337 | 348 | #define MC417_OEN 0x00110024 |
338 | 349 | #define MC417_CTL 0x00110028 |
350 | +#define ALT_PIN_OUT_SEL 0x0011002C | |
339 | 351 | #define CLK_DELAY 0x00110048 |
340 | 352 | #define PAD_CTRL 0x0011004C |
341 | 353 |
drivers/media/video/cx23885/cx23885.h
... | ... | @@ -44,6 +44,10 @@ |
44 | 44 | |
45 | 45 | /* Max number of inputs by card */ |
46 | 46 | #define MAX_CX23885_INPUT 8 |
47 | +#define INPUT(nr) (&cx23885_boards[dev->board].input[nr]) | |
48 | +#define RESOURCE_OVERLAY 1 | |
49 | +#define RESOURCE_VIDEO 2 | |
50 | +#define RESOURCE_VBI 4 | |
47 | 51 | |
48 | 52 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ |
49 | 53 | |
... | ... | @@ -56,6 +60,60 @@ |
56 | 60 | #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5 |
57 | 61 | #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 |
58 | 62 | |
63 | +/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ | |
64 | +#define CX23885_NORMS (\ | |
65 | + V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443 | \ | |
66 | + V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ | |
67 | + V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \ | |
68 | + V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK) | |
69 | + | |
70 | +struct cx23885_fmt { | |
71 | + char *name; | |
72 | + u32 fourcc; /* v4l2 format id */ | |
73 | + int depth; | |
74 | + int flags; | |
75 | + u32 cxformat; | |
76 | +}; | |
77 | + | |
78 | +struct cx23885_ctrl { | |
79 | + struct v4l2_queryctrl v; | |
80 | + u32 off; | |
81 | + u32 reg; | |
82 | + u32 mask; | |
83 | + u32 shift; | |
84 | +}; | |
85 | + | |
86 | +struct cx23885_tvnorm { | |
87 | + char *name; | |
88 | + v4l2_std_id id; | |
89 | + u32 cxiformat; | |
90 | + u32 cxoformat; | |
91 | +}; | |
92 | + | |
93 | +struct cx23885_fh { | |
94 | + struct cx23885_dev *dev; | |
95 | + enum v4l2_buf_type type; | |
96 | + int radio; | |
97 | + u32 resources; | |
98 | + | |
99 | + /* video overlay */ | |
100 | + struct v4l2_window win; | |
101 | + struct v4l2_clip *clips; | |
102 | + unsigned int nclips; | |
103 | + | |
104 | + /* video capture */ | |
105 | + struct cx23885_fmt *fmt; | |
106 | + unsigned int width, height; | |
107 | + | |
108 | + /* vbi capture */ | |
109 | + struct videobuf_queue vidq; | |
110 | + struct videobuf_queue vbiq; | |
111 | + | |
112 | + /* MPEG Encoder specifics ONLY */ | |
113 | + struct videobuf_queue mpegq; | |
114 | + atomic_t v4l_reading; | |
115 | +}; | |
116 | + | |
59 | 117 | enum cx23885_itype { |
60 | 118 | CX23885_VMUX_COMPOSITE1 = 1, |
61 | 119 | CX23885_VMUX_COMPOSITE2, |
62 | 120 | |
... | ... | @@ -94,12 +152,17 @@ |
94 | 152 | |
95 | 153 | typedef enum { |
96 | 154 | CX23885_MPEG_UNDEFINED = 0, |
97 | - CX23885_MPEG_DVB | |
155 | + CX23885_MPEG_DVB, | |
156 | + CX23885_ANALOG_VIDEO, | |
98 | 157 | } port_t; |
99 | 158 | |
100 | 159 | struct cx23885_board { |
101 | 160 | char *name; |
102 | - port_t portb, portc; | |
161 | + port_t porta, portb, portc; | |
162 | + unsigned int tuner_type; | |
163 | + unsigned int radio_type; | |
164 | + unsigned char tuner_addr; | |
165 | + unsigned char radio_addr; | |
103 | 166 | |
104 | 167 | /* Vendors can and do run the PCIe bridge at different |
105 | 168 | * clock rates, driven physically by crystals on the PCBs. |
106 | 169 | |
... | ... | @@ -228,8 +291,31 @@ |
228 | 291 | CX23885_BRIDGE_885 = 885, |
229 | 292 | CX23885_BRIDGE_887 = 887, |
230 | 293 | } bridge; |
294 | + | |
295 | + /* Analog video */ | |
296 | + u32 resources; | |
297 | + unsigned int input; | |
298 | + u32 tvaudio; | |
299 | + v4l2_std_id tvnorm; | |
300 | + unsigned int tuner_type; | |
301 | + unsigned char tuner_addr; | |
302 | + unsigned int radio_type; | |
303 | + unsigned char radio_addr; | |
304 | + unsigned int has_radio; | |
305 | + | |
306 | + /* V4l */ | |
307 | + u32 freq; | |
308 | + struct video_device *video_dev; | |
309 | + struct video_device *vbi_dev; | |
310 | + struct video_device *radio_dev; | |
311 | + | |
312 | + struct cx23885_dmaqueue vidq; | |
313 | + struct cx23885_dmaqueue vbiq; | |
314 | + spinlock_t slock; | |
231 | 315 | }; |
232 | 316 | |
317 | +extern struct list_head cx23885_devlist; | |
318 | + | |
233 | 319 | #define SRAM_CH01 0 /* Video A */ |
234 | 320 | #define SRAM_CH02 1 /* VBI A */ |
235 | 321 | #define SRAM_CH03 2 /* Video B */ |
236 | 322 | |
... | ... | @@ -273,8 +359,34 @@ |
273 | 359 | #define cx_clear(reg,bit) cx_andor((reg),(bit),0) |
274 | 360 | |
275 | 361 | /* ----------------------------------------------------------- */ |
276 | -/* cx23885-cards.c */ | |
362 | +/* cx23885-core.c */ | |
277 | 363 | |
364 | +extern int cx23885_sram_channel_setup(struct cx23885_dev *dev, | |
365 | + struct sram_channel *ch, | |
366 | + unsigned int bpl, u32 risc); | |
367 | + | |
368 | +extern void cx23885_sram_channel_dump(struct cx23885_dev *dev, | |
369 | + struct sram_channel *ch); | |
370 | + | |
371 | +extern int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | |
372 | + u32 reg, u32 mask, u32 value); | |
373 | + | |
374 | +extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |
375 | + struct scatterlist *sglist, | |
376 | + unsigned int top_offset, unsigned int bottom_offset, | |
377 | + unsigned int bpl, unsigned int padding, unsigned int lines); | |
378 | + | |
379 | +void cx23885_cancel_buffers(struct cx23885_tsport *port); | |
380 | + | |
381 | +extern int cx23885_restart_queue(struct cx23885_tsport *port, | |
382 | + struct cx23885_dmaqueue *q); | |
383 | + | |
384 | +extern void cx23885_wakeup(struct cx23885_tsport *port, | |
385 | + struct cx23885_dmaqueue *q, u32 count); | |
386 | + | |
387 | + | |
388 | +/* ----------------------------------------------------------- */ | |
389 | +/* cx23885-cards.c */ | |
278 | 390 | extern struct cx23885_board cx23885_boards[]; |
279 | 391 | extern const unsigned int cx23885_bcount; |
280 | 392 | |
281 | 393 | |
282 | 394 | |
... | ... | @@ -294,18 +406,49 @@ |
294 | 406 | struct cx23885_tsport *port, |
295 | 407 | struct cx23885_buffer *buf, |
296 | 408 | enum v4l2_field field); |
297 | - | |
298 | 409 | extern void cx23885_buf_queue(struct cx23885_tsport *port, |
299 | 410 | struct cx23885_buffer *buf); |
300 | 411 | extern void cx23885_free_buffer(struct videobuf_queue *q, |
301 | 412 | struct cx23885_buffer *buf); |
302 | 413 | |
303 | 414 | /* ----------------------------------------------------------- */ |
415 | +/* cx23885-video.c */ | |
416 | +/* Video */ | |
417 | +extern int cx23885_video_register(struct cx23885_dev *dev); | |
418 | +extern void cx23885_video_unregister(struct cx23885_dev *dev); | |
419 | +extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status); | |
420 | + | |
421 | +/* ----------------------------------------------------------- */ | |
422 | +/* cx23885-vbi.c */ | |
423 | +extern int cx23885_vbi_fmt(struct file *file, void *priv, | |
424 | + struct v4l2_format *f); | |
425 | +extern void cx23885_vbi_timeout(unsigned long data); | |
426 | +extern struct videobuf_queue_ops cx23885_vbi_qops; | |
427 | + | |
304 | 428 | /* cx23885-i2c.c */ |
305 | 429 | extern int cx23885_i2c_register(struct cx23885_i2c *bus); |
306 | 430 | extern int cx23885_i2c_unregister(struct cx23885_i2c *bus); |
307 | 431 | extern void cx23885_call_i2c_clients(struct cx23885_i2c *bus, unsigned int cmd, |
308 | 432 | void *arg); |
433 | + | |
434 | +/* ----------------------------------------------------------- */ | |
435 | +/* tv norms */ | |
436 | + | |
437 | +static inline unsigned int norm_maxw(v4l2_std_id norm) | |
438 | +{ | |
439 | + return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; | |
440 | +} | |
441 | + | |
442 | +static inline unsigned int norm_maxh(v4l2_std_id norm) | |
443 | +{ | |
444 | + return (norm & V4L2_STD_625_50) ? 576 : 480; | |
445 | +} | |
446 | + | |
447 | +static inline unsigned int norm_swidth(v4l2_std_id norm) | |
448 | +{ | |
449 | + return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922; | |
450 | +} | |
451 | + | |
309 | 452 | |
310 | 453 | /* |
311 | 454 | * Local variables: |