diff options
author | Steven Toth <stoth@hauppauge.com> | 2008-01-13 21:42:44 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:09:50 -0400 |
commit | b1b81f1db73f00e595585b16aa31293a791964c0 (patch) | |
tree | 3e348070d6c08cf421729f36005e91b50c89ab98 /drivers/media/video/cx23885/cx23885-core.c | |
parent | e57b1c80065f7922e3ba464f54254c7ce983a3a4 (diff) |
V4L/DVB (7725): cx23885: Add generic cx23417 hardware encoder support
cx23885: Add generic cx23417 hardware encoder support.
Signed-off-by: Steven Toth <stoth@hauppauge.com>
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-core.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-core.c | 163 |
1 files changed, 133 insertions, 30 deletions
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index b23d60801ed0..7f7446a76465 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -190,25 +190,25 @@ static struct sram_channel cx23887_sram_channels[] = { | |||
190 | static int cx23885_risc_decode(u32 risc) | 190 | static int cx23885_risc_decode(u32 risc) |
191 | { | 191 | { |
192 | static char *instr[16] = { | 192 | static char *instr[16] = { |
193 | [ RISC_SYNC >> 28 ] = "sync", | 193 | [RISC_SYNC >> 28] = "sync", |
194 | [ RISC_WRITE >> 28 ] = "write", | 194 | [RISC_WRITE >> 28] = "write", |
195 | [ RISC_WRITEC >> 28 ] = "writec", | 195 | [RISC_WRITEC >> 28] = "writec", |
196 | [ RISC_READ >> 28 ] = "read", | 196 | [RISC_READ >> 28] = "read", |
197 | [ RISC_READC >> 28 ] = "readc", | 197 | [RISC_READC >> 28] = "readc", |
198 | [ RISC_JUMP >> 28 ] = "jump", | 198 | [RISC_JUMP >> 28] = "jump", |
199 | [ RISC_SKIP >> 28 ] = "skip", | 199 | [RISC_SKIP >> 28] = "skip", |
200 | [ RISC_WRITERM >> 28 ] = "writerm", | 200 | [RISC_WRITERM >> 28] = "writerm", |
201 | [ RISC_WRITECM >> 28 ] = "writecm", | 201 | [RISC_WRITECM >> 28] = "writecm", |
202 | [ RISC_WRITECR >> 28 ] = "writecr", | 202 | [RISC_WRITECR >> 28] = "writecr", |
203 | }; | 203 | }; |
204 | static int incr[16] = { | 204 | static int incr[16] = { |
205 | [ RISC_WRITE >> 28 ] = 3, | 205 | [RISC_WRITE >> 28] = 3, |
206 | [ RISC_JUMP >> 28 ] = 3, | 206 | [RISC_JUMP >> 28] = 3, |
207 | [ RISC_SKIP >> 28 ] = 1, | 207 | [RISC_SKIP >> 28] = 1, |
208 | [ RISC_SYNC >> 28 ] = 1, | 208 | [RISC_SYNC >> 28] = 1, |
209 | [ RISC_WRITERM >> 28 ] = 3, | 209 | [RISC_WRITERM >> 28] = 3, |
210 | [ RISC_WRITECM >> 28 ] = 3, | 210 | [RISC_WRITECM >> 28] = 3, |
211 | [ RISC_WRITECR >> 28 ] = 4, | 211 | [RISC_WRITECR >> 28] = 4, |
212 | }; | 212 | }; |
213 | static char *bits[] = { | 213 | static char *bits[] = { |
214 | "12", "13", "14", "resync", | 214 | "12", "13", "14", "resync", |
@@ -518,6 +518,8 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p | |||
518 | /* Transport bus init dma queue - Common settings */ | 518 | /* Transport bus init dma queue - Common settings */ |
519 | port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */ | 519 | port->dma_ctl_val = 0x11; /* Enable RISC controller and Fifo */ |
520 | port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */ | 520 | port->ts_int_msk_val = 0x1111; /* TS port bits for RISC */ |
521 | port->vld_misc_val = 0x0; | ||
522 | port->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4); | ||
521 | 523 | ||
522 | spin_lock_init(&port->slock); | 524 | spin_lock_init(&port->slock); |
523 | port->dev = dev; | 525 | port->dev = dev; |
@@ -544,7 +546,7 @@ static int cx23885_init_tsport(struct cx23885_dev *dev, struct cx23885_tsport *p | |||
544 | port->reg_ts_clk_en = VID_B_TS_CLK_EN; | 546 | port->reg_ts_clk_en = VID_B_TS_CLK_EN; |
545 | port->reg_src_sel = VID_B_SRC_SEL; | 547 | port->reg_src_sel = VID_B_SRC_SEL; |
546 | port->reg_ts_int_msk = VID_B_INT_MSK; | 548 | port->reg_ts_int_msk = VID_B_INT_MSK; |
547 | port->reg_ts_int_stat = VID_B_INT_STAT; | 549 | port->reg_ts_int_stat = VID_B_INT_STAT; |
548 | port->sram_chno = SRAM_CH03; /* VID_B */ | 550 | port->sram_chno = SRAM_CH03; /* VID_B */ |
549 | port->pci_irqmask = 0x02; /* VID_B bit1 */ | 551 | port->pci_irqmask = 0x02; /* VID_B bit1 */ |
550 | break; | 552 | break; |
@@ -697,10 +699,12 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) | |||
697 | dev->i2c_bus[2].reg_wdata = I2C3_WDATA; | 699 | dev->i2c_bus[2].reg_wdata = I2C3_WDATA; |
698 | dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ | 700 | dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */ |
699 | 701 | ||
700 | if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) | 702 | if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) || |
703 | (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)) | ||
701 | cx23885_init_tsport(dev, &dev->ts1, 1); | 704 | cx23885_init_tsport(dev, &dev->ts1, 1); |
702 | 705 | ||
703 | if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | 706 | if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) || |
707 | (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)) | ||
704 | cx23885_init_tsport(dev, &dev->ts2, 2); | 708 | cx23885_init_tsport(dev, &dev->ts2, 2); |
705 | 709 | ||
706 | if (get_resources(dev) < 0) { | 710 | if (get_resources(dev) < 0) { |
@@ -760,11 +764,26 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) | |||
760 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", | 764 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n", |
761 | __func__); | 765 | __func__); |
762 | } | 766 | } |
767 | } else | ||
768 | if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) { | ||
769 | if (cx23885_417_register(dev) < 0) { | ||
770 | printk(KERN_ERR | ||
771 | "%s() Failed to register 417 on VID_B\n", | ||
772 | __func__); | ||
773 | } | ||
763 | } | 774 | } |
764 | 775 | ||
765 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { | 776 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) { |
766 | if (cx23885_dvb_register(&dev->ts2) < 0) { | 777 | if (cx23885_dvb_register(&dev->ts2) < 0) { |
767 | printk(KERN_ERR "%s() Failed to register dvb adapters on VID_C\n", | 778 | printk(KERN_ERR |
779 | "%s() Failed to register dvb on VID_C\n", | ||
780 | __func__); | ||
781 | } | ||
782 | } else | ||
783 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) { | ||
784 | if (cx23885_417_register(dev) < 0) { | ||
785 | printk(KERN_ERR | ||
786 | "%s() Failed to register 417 on VID_C\n", | ||
768 | __func__); | 787 | __func__); |
769 | } | 788 | } |
770 | } | 789 | } |
@@ -785,12 +804,18 @@ static void cx23885_dev_unregister(struct cx23885_dev *dev) | |||
785 | if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) | 804 | if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) |
786 | cx23885_video_unregister(dev); | 805 | cx23885_video_unregister(dev); |
787 | 806 | ||
788 | if(cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) | 807 | if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) |
789 | cx23885_dvb_unregister(&dev->ts1); | 808 | cx23885_dvb_unregister(&dev->ts1); |
790 | 809 | ||
791 | if(cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | 810 | if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) |
811 | cx23885_417_unregister(dev); | ||
812 | |||
813 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | ||
792 | cx23885_dvb_unregister(&dev->ts2); | 814 | cx23885_dvb_unregister(&dev->ts2); |
793 | 815 | ||
816 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) | ||
817 | cx23885_417_unregister(dev); | ||
818 | |||
794 | cx23885_i2c_unregister(&dev->i2c_bus[2]); | 819 | cx23885_i2c_unregister(&dev->i2c_bus[2]); |
795 | cx23885_i2c_unregister(&dev->i2c_bus[1]); | 820 | cx23885_i2c_unregister(&dev->i2c_bus[1]); |
796 | cx23885_i2c_unregister(&dev->i2c_bus[0]); | 821 | cx23885_i2c_unregister(&dev->i2c_bus[0]); |
@@ -1043,9 +1068,9 @@ static int cx23885_start_dma(struct cx23885_tsport *port, | |||
1043 | if(port->reg_src_sel) | 1068 | if(port->reg_src_sel) |
1044 | cx_write(port->reg_src_sel, port->src_sel_val); | 1069 | cx_write(port->reg_src_sel, port->src_sel_val); |
1045 | 1070 | ||
1046 | cx_write(port->reg_hw_sop_ctrl, 0x47 << 16 | 188 << 4); | 1071 | cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val); |
1047 | cx_write(port->reg_ts_clk_en, port->ts_clk_en_val); | 1072 | cx_write(port->reg_ts_clk_en, port->ts_clk_en_val); |
1048 | cx_write(port->reg_vld_misc, 0x00); | 1073 | cx_write(port->reg_vld_misc, port->vld_misc_val); |
1049 | cx_write(port->reg_gen_ctrl, port->gen_ctrl_val); | 1074 | cx_write(port->reg_gen_ctrl, port->gen_ctrl_val); |
1050 | udelay(100); | 1075 | udelay(100); |
1051 | 1076 | ||
@@ -1239,6 +1264,16 @@ static void do_cancel_buffers(struct cx23885_tsport *port, char *reason, | |||
1239 | spin_unlock_irqrestore(&port->slock, flags); | 1264 | spin_unlock_irqrestore(&port->slock, flags); |
1240 | } | 1265 | } |
1241 | 1266 | ||
1267 | void cx23885_cancel_buffers(struct cx23885_tsport *port) | ||
1268 | { | ||
1269 | struct cx23885_dev *dev = port->dev; | ||
1270 | struct cx23885_dmaqueue *q = &port->mpegq; | ||
1271 | |||
1272 | dprintk(1, "%s()\n", __FUNCTION__); | ||
1273 | del_timer_sync(&q->timeout); | ||
1274 | cx23885_stop_dma(port); | ||
1275 | do_cancel_buffers(port, "cancel", 0); | ||
1276 | } | ||
1242 | 1277 | ||
1243 | static void cx23885_timeout(unsigned long data) | 1278 | static void cx23885_timeout(unsigned long data) |
1244 | { | 1279 | { |
@@ -1254,16 +1289,77 @@ static void cx23885_timeout(unsigned long data) | |||
1254 | do_cancel_buffers(port, "timeout", 1); | 1289 | do_cancel_buffers(port, "timeout", 1); |
1255 | } | 1290 | } |
1256 | 1291 | ||
1292 | int cx23885_irq_417(struct cx23885_dev *dev, u32 status) | ||
1293 | { | ||
1294 | /* FIXME: port1 assumption here. */ | ||
1295 | struct cx23885_tsport *port = &dev->ts1; | ||
1296 | int count = 0; | ||
1297 | int handled = 0; | ||
1298 | |||
1299 | if (status == 0) | ||
1300 | return handled; | ||
1301 | |||
1302 | count = cx_read(port->reg_gpcnt); | ||
1303 | dprintk(7, "status: 0x%08x mask: 0x%08x count: 0x%x\n", | ||
1304 | status, cx_read(port->reg_ts_int_msk), count); | ||
1305 | |||
1306 | if ((status & VID_B_MSK_BAD_PKT) || | ||
1307 | (status & VID_B_MSK_OPC_ERR) || | ||
1308 | (status & VID_B_MSK_VBI_OPC_ERR) || | ||
1309 | (status & VID_B_MSK_SYNC) || | ||
1310 | (status & VID_B_MSK_VBI_SYNC) || | ||
1311 | (status & VID_B_MSK_OF) || | ||
1312 | (status & VID_B_MSK_VBI_OF)) { | ||
1313 | printk(KERN_ERR "%s: V4L mpeg risc op code error, status " | ||
1314 | "= 0x%x\n", dev->name, status); | ||
1315 | if (status & VID_B_MSK_BAD_PKT) | ||
1316 | dprintk(1, " VID_B_MSK_BAD_PKT\n"); | ||
1317 | if (status & VID_B_MSK_OPC_ERR) | ||
1318 | dprintk(1, " VID_B_MSK_OPC_ERR\n"); | ||
1319 | if (status & VID_B_MSK_VBI_OPC_ERR) | ||
1320 | dprintk(1, " VID_B_MSK_VBI_OPC_ERR\n"); | ||
1321 | if (status & VID_B_MSK_SYNC) | ||
1322 | dprintk(1, " VID_B_MSK_SYNC\n"); | ||
1323 | if (status & VID_B_MSK_VBI_SYNC) | ||
1324 | dprintk(1, " VID_B_MSK_VBI_SYNC\n"); | ||
1325 | if (status & VID_B_MSK_OF) | ||
1326 | dprintk(1, " VID_B_MSK_OF\n"); | ||
1327 | if (status & VID_B_MSK_VBI_OF) | ||
1328 | dprintk(1, " VID_B_MSK_VBI_OF\n"); | ||
1329 | |||
1330 | cx_clear(port->reg_dma_ctl, port->dma_ctl_val); | ||
1331 | cx23885_sram_channel_dump(dev, | ||
1332 | &dev->sram_channels[port->sram_chno]); | ||
1333 | cx23885_417_check_encoder(dev); | ||
1334 | } else if (status & VID_B_MSK_RISCI1) { | ||
1335 | dprintk(7, " VID_B_MSK_RISCI1\n"); | ||
1336 | spin_lock(&port->slock); | ||
1337 | cx23885_wakeup(port, &port->mpegq, count); | ||
1338 | spin_unlock(&port->slock); | ||
1339 | } else if (status & VID_B_MSK_RISCI2) { | ||
1340 | dprintk(7, " VID_B_MSK_RISCI2\n"); | ||
1341 | spin_lock(&port->slock); | ||
1342 | cx23885_restart_queue(port, &port->mpegq); | ||
1343 | spin_unlock(&port->slock); | ||
1344 | } | ||
1345 | if (status) { | ||
1346 | cx_write(port->reg_ts_int_stat, status); | ||
1347 | handled = 1; | ||
1348 | } | ||
1349 | |||
1350 | return handled; | ||
1351 | } | ||
1352 | |||
1257 | static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) | 1353 | static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) |
1258 | { | 1354 | { |
1259 | struct cx23885_dev *dev = port->dev; | 1355 | struct cx23885_dev *dev = port->dev; |
1260 | int handled = 0; | 1356 | int handled = 0; |
1261 | u32 count; | 1357 | u32 count; |
1262 | 1358 | ||
1263 | if ( (status & VID_BC_MSK_OPC_ERR) || | 1359 | if ((status & VID_BC_MSK_OPC_ERR) || |
1264 | (status & VID_BC_MSK_BAD_PKT) || | 1360 | (status & VID_BC_MSK_BAD_PKT) || |
1265 | (status & VID_BC_MSK_SYNC) || | 1361 | (status & VID_BC_MSK_SYNC) || |
1266 | (status & VID_BC_MSK_OF)) | 1362 | (status & VID_BC_MSK_OF)) |
1267 | { | 1363 | { |
1268 | if (status & VID_BC_MSK_OPC_ERR) | 1364 | if (status & VID_BC_MSK_OPC_ERR) |
1269 | dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR); | 1365 | dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n", VID_BC_MSK_OPC_ERR); |
@@ -1277,7 +1373,8 @@ static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status) | |||
1277 | printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name); | 1373 | printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name); |
1278 | 1374 | ||
1279 | cx_clear(port->reg_dma_ctl, port->dma_ctl_val); | 1375 | cx_clear(port->reg_dma_ctl, port->dma_ctl_val); |
1280 | cx23885_sram_channel_dump(dev, &dev->sram_channels[ port->sram_chno ]); | 1376 | cx23885_sram_channel_dump(dev, |
1377 | &dev->sram_channels[port->sram_chno]); | ||
1281 | 1378 | ||
1282 | } else if (status & VID_BC_MSK_RISCI1) { | 1379 | } else if (status & VID_BC_MSK_RISCI1) { |
1283 | 1380 | ||
@@ -1378,11 +1475,17 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) | |||
1378 | if (ts1_status) { | 1475 | if (ts1_status) { |
1379 | if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) | 1476 | if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) |
1380 | handled += cx23885_irq_ts(ts1, ts1_status); | 1477 | handled += cx23885_irq_ts(ts1, ts1_status); |
1478 | else | ||
1479 | if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) | ||
1480 | handled += cx23885_irq_417(dev, ts1_status); | ||
1381 | } | 1481 | } |
1382 | 1482 | ||
1383 | if (ts2_status) { | 1483 | if (ts2_status) { |
1384 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) | 1484 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) |
1385 | handled += cx23885_irq_ts(ts2, ts2_status); | 1485 | handled += cx23885_irq_ts(ts2, ts2_status); |
1486 | else | ||
1487 | if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) | ||
1488 | handled += cx23885_irq_417(dev, ts2_status); | ||
1386 | } | 1489 | } |
1387 | 1490 | ||
1388 | if (vida_status) | 1491 | if (vida_status) |