cx88-mpeg.c (6f11adc6a5e3378aeb13d9a19c427cbec05805be) | cx88-mpeg.c (0b6b6302d983236f8b5d6d6602b91a6d1e144896) |
---|---|
1/* 2 * 3 * Support for the mpeg transport stream transfers 4 * PCI function #2 of the cx2388x. 5 * 6 * (c) 2004 Jelle Foks <jelle@foks.us> 7 * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au> 8 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> --- 72 unchanged lines hidden (view full) --- 81#define flush_request_modules(dev) 82#endif /* CONFIG_MODULES */ 83 84 85static LIST_HEAD(cx8802_devlist); 86static DEFINE_MUTEX(cx8802_mutex); 87/* ------------------------------------------------------------------ */ 88 | 1/* 2 * 3 * Support for the mpeg transport stream transfers 4 * PCI function #2 of the cx2388x. 5 * 6 * (c) 2004 Jelle Foks <jelle@foks.us> 7 * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au> 8 * (c) 2004 Gerd Knorr <kraxel@bytesex.org> --- 72 unchanged lines hidden (view full) --- 81#define flush_request_modules(dev) 82#endif /* CONFIG_MODULES */ 83 84 85static LIST_HEAD(cx8802_devlist); 86static DEFINE_MUTEX(cx8802_mutex); 87/* ------------------------------------------------------------------ */ 88 |
89static int cx8802_start_dma(struct cx8802_dev *dev, | 89int cx8802_start_dma(struct cx8802_dev *dev, |
90 struct cx88_dmaqueue *q, 91 struct cx88_buffer *buf) 92{ 93 struct cx88_core *core = dev->core; 94 95 dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", | 90 struct cx88_dmaqueue *q, 91 struct cx88_buffer *buf) 92{ 93 struct cx88_core *core = dev->core; 94 95 dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", |
96 buf->vb.width, buf->vb.height, buf->vb.field); | 96 dev->width, dev->height, dev->field); |
97 98 /* setup fifo + format */ 99 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 100 dev->ts_packet_size, buf->risc.dma); 101 102 /* write TS length to chip */ | 97 98 /* setup fifo + format */ 99 cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 100 dev->ts_packet_size, buf->risc.dma); 101 102 /* write TS length to chip */ |
103 cx_write(MO_TS_LNGTH, buf->vb.width); | 103 cx_write(MO_TS_LNGTH, dev->ts_packet_size); |
104 105 /* FIXME: this needs a review. 106 * also: move to cx88-blackbird + cx88-dvb source files? */ 107 108 dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); 109 110 if ( (core->active_type_id == CX88_MPEG_DVB) && 111 (core->board.mpeg & CX88_MPEG_DVB) ) { --- 95 unchanged lines hidden (view full) --- 207 struct cx88_dmaqueue *q) 208{ 209 struct cx88_buffer *buf; 210 211 dprintk( 1, "cx8802_restart_queue\n" ); 212 if (list_empty(&q->active)) 213 return 0; 214 | 104 105 /* FIXME: this needs a review. 106 * also: move to cx88-blackbird + cx88-dvb source files? */ 107 108 dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id); 109 110 if ( (core->active_type_id == CX88_MPEG_DVB) && 111 (core->board.mpeg & CX88_MPEG_DVB) ) { --- 95 unchanged lines hidden (view full) --- 207 struct cx88_dmaqueue *q) 208{ 209 struct cx88_buffer *buf; 210 211 dprintk( 1, "cx8802_restart_queue\n" ); 212 if (list_empty(&q->active)) 213 return 0; 214 |
215 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 215 buf = list_entry(q->active.next, struct cx88_buffer, list); |
216 dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 216 dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
217 buf, buf->vb.i); | 217 buf, buf->vb.v4l2_buf.index); |
218 cx8802_start_dma(dev, q, buf); | 218 cx8802_start_dma(dev, q, buf); |
219 list_for_each_entry(buf, &q->active, vb.queue) | 219 list_for_each_entry(buf, &q->active, list) |
220 buf->count = q->count++; | 220 buf->count = q->count++; |
221 mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | |
222 return 0; 223} 224 225/* ------------------------------------------------------------------ */ 226 | 221 return 0; 222} 223 224/* ------------------------------------------------------------------ */ 225 |
227int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, | 226int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev, |
228 struct cx88_buffer *buf, enum v4l2_field field) 229{ 230 int size = dev->ts_packet_size * dev->ts_packet_count; | 227 struct cx88_buffer *buf, enum v4l2_field field) 228{ 229 int size = dev->ts_packet_size * dev->ts_packet_count; |
231 struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | 230 struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0); |
232 int rc; 233 | 231 int rc; 232 |
234 dprintk(1, "%s: %p\n", __func__, buf); 235 if (0 != buf->vb.baddr && buf->vb.bsize < size) | 233 if (vb2_plane_size(&buf->vb, 0) < size) |
236 return -EINVAL; | 234 return -EINVAL; |
235 vb2_set_plane_payload(&buf->vb, 0, size); |
|
237 | 236 |
238 if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { 239 buf->vb.width = dev->ts_packet_size; 240 buf->vb.height = dev->ts_packet_count; 241 buf->vb.size = size; 242 buf->vb.field = field /*V4L2_FIELD_TOP*/; | 237 rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); 238 if (!rc) 239 return -EIO; |
243 | 240 |
244 if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) 245 goto fail; 246 cx88_risc_databuffer(dev->pci, &buf->risc, 247 dma->sglist, 248 buf->vb.width, buf->vb.height, 0); 249 } 250 buf->vb.state = VIDEOBUF_PREPARED; | 241 cx88_risc_databuffer(dev->pci, &buf->risc, sgt->sgl, 242 dev->ts_packet_size, dev->ts_packet_count, 0); |
251 return 0; | 243 return 0; |
252 253 fail: 254 cx88_free_buffer(q,buf); 255 return rc; | |
256} 257 258void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) 259{ 260 struct cx88_buffer *prev; 261 struct cx88_dmaqueue *cx88q = &dev->mpegq; 262 263 dprintk( 1, "cx8802_buf_queue\n" ); | 244} 245 246void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) 247{ 248 struct cx88_buffer *prev; 249 struct cx88_dmaqueue *cx88q = &dev->mpegq; 250 251 dprintk( 1, "cx8802_buf_queue\n" ); |
264 /* add jump to stopper */ 265 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); 266 buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); | 252 /* add jump to start */ 253 buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8); 254 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); 255 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8); |
267 268 if (list_empty(&cx88q->active)) { 269 dprintk( 1, "queue is empty - first active\n" ); | 256 257 if (list_empty(&cx88q->active)) { 258 dprintk( 1, "queue is empty - first active\n" ); |
270 list_add_tail(&buf->vb.queue,&cx88q->active); 271 cx8802_start_dma(dev, cx88q, buf); 272 buf->vb.state = VIDEOBUF_ACTIVE; | 259 list_add_tail(&buf->list, &cx88q->active); |
273 buf->count = cx88q->count++; | 260 buf->count = cx88q->count++; |
274 mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); | |
275 dprintk(1,"[%p/%d] %s - first active\n", | 261 dprintk(1,"[%p/%d] %s - first active\n", |
276 buf, buf->vb.i, __func__); | 262 buf, buf->vb.v4l2_buf.index, __func__); |
277 278 } else { | 263 264 } else { |
265 buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); |
|
279 dprintk( 1, "queue is not empty - append to active\n" ); | 266 dprintk( 1, "queue is not empty - append to active\n" ); |
280 prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue); 281 list_add_tail(&buf->vb.queue,&cx88q->active); 282 buf->vb.state = VIDEOBUF_ACTIVE; | 267 prev = list_entry(cx88q->active.prev, struct cx88_buffer, list); 268 list_add_tail(&buf->list, &cx88q->active); |
283 buf->count = cx88q->count++; 284 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 285 dprintk( 1, "[%p/%d] %s - append to active\n", | 269 buf->count = cx88q->count++; 270 prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 271 dprintk( 1, "[%p/%d] %s - append to active\n", |
286 buf, buf->vb.i, __func__); | 272 buf, buf->vb.v4l2_buf.index, __func__); |
287 } 288} 289 290/* ----------------------------------------------------------- */ 291 | 273 } 274} 275 276/* ----------------------------------------------------------- */ 277 |
292static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart) | 278static void do_cancel_buffers(struct cx8802_dev *dev) |
293{ 294 struct cx88_dmaqueue *q = &dev->mpegq; 295 struct cx88_buffer *buf; 296 unsigned long flags; 297 298 spin_lock_irqsave(&dev->slock,flags); 299 while (!list_empty(&q->active)) { | 279{ 280 struct cx88_dmaqueue *q = &dev->mpegq; 281 struct cx88_buffer *buf; 282 unsigned long flags; 283 284 spin_lock_irqsave(&dev->slock,flags); 285 while (!list_empty(&q->active)) { |
300 buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); 301 list_del(&buf->vb.queue); 302 buf->vb.state = VIDEOBUF_ERROR; 303 wake_up(&buf->vb.done); 304 dprintk(1,"[%p/%d] %s - dma=0x%08lx\n", 305 buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); | 286 buf = list_entry(q->active.next, struct cx88_buffer, list); 287 list_del(&buf->list); 288 vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); |
306 } | 289 } |
307 if (restart) 308 { 309 dprintk(1, "restarting queue\n" ); 310 cx8802_restart_queue(dev,q); 311 } | |
312 spin_unlock_irqrestore(&dev->slock,flags); 313} 314 315void cx8802_cancel_buffers(struct cx8802_dev *dev) 316{ | 290 spin_unlock_irqrestore(&dev->slock,flags); 291} 292 293void cx8802_cancel_buffers(struct cx8802_dev *dev) 294{ |
317 struct cx88_dmaqueue *q = &dev->mpegq; 318 | |
319 dprintk( 1, "cx8802_cancel_buffers" ); | 295 dprintk( 1, "cx8802_cancel_buffers" ); |
320 del_timer_sync(&q->timeout); | |
321 cx8802_stop_dma(dev); | 296 cx8802_stop_dma(dev); |
322 do_cancel_buffers(dev,"cancel",0); | 297 do_cancel_buffers(dev); |
323} 324 | 298} 299 |
325static void cx8802_timeout(unsigned long data) 326{ 327 struct cx8802_dev *dev = (struct cx8802_dev*)data; 328 329 dprintk(1, "%s\n",__func__); 330 331 if (debug) 332 cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); 333 cx8802_stop_dma(dev); 334 do_cancel_buffers(dev,"timeout",1); 335} 336 | |
337static const char * cx88_mpeg_irqs[32] = { 338 "ts_risci1", NULL, NULL, NULL, 339 "ts_risci2", NULL, NULL, NULL, 340 "ts_oflow", NULL, NULL, NULL, 341 "ts_sync", NULL, NULL, NULL, 342 "opc_err", "par_err", "rip_err", "pci_abort", 343 "ts_err?", 344}; --- 27 unchanged lines hidden (view full) --- 372 if (status & 0x01) { 373 dprintk( 1, "wake up\n" ); 374 spin_lock(&dev->slock); 375 count = cx_read(MO_TS_GPCNT); 376 cx88_wakeup(dev->core, &dev->mpegq, count); 377 spin_unlock(&dev->slock); 378 } 379 | 300static const char * cx88_mpeg_irqs[32] = { 301 "ts_risci1", NULL, NULL, NULL, 302 "ts_risci2", NULL, NULL, NULL, 303 "ts_oflow", NULL, NULL, NULL, 304 "ts_sync", NULL, NULL, NULL, 305 "opc_err", "par_err", "rip_err", "pci_abort", 306 "ts_err?", 307}; --- 27 unchanged lines hidden (view full) --- 335 if (status & 0x01) { 336 dprintk( 1, "wake up\n" ); 337 spin_lock(&dev->slock); 338 count = cx_read(MO_TS_GPCNT); 339 cx88_wakeup(dev->core, &dev->mpegq, count); 340 spin_unlock(&dev->slock); 341 } 342 |
380 /* risc2 y */ 381 if (status & 0x10) { 382 spin_lock(&dev->slock); 383 cx8802_restart_queue(dev,&dev->mpegq); 384 spin_unlock(&dev->slock); 385 } 386 | |
387 /* other general errors */ 388 if (status & 0x1f0100) { 389 dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); 390 spin_lock(&dev->slock); 391 cx8802_stop_dma(dev); | 343 /* other general errors */ 344 if (status & 0x1f0100) { 345 dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); 346 spin_lock(&dev->slock); 347 cx8802_stop_dma(dev); |
392 cx8802_restart_queue(dev,&dev->mpegq); | |
393 spin_unlock(&dev->slock); 394 } 395} 396 397#define MAX_IRQ_LOOP 10 398 399static irqreturn_t cx8802_irq(int irq, void *dev_id) 400{ --- 50 unchanged lines hidden (view full) --- 451 pci_name(dev->pci), dev->pci_rev, dev->pci->irq, 452 dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0)); 453 454 /* initialize driver struct */ 455 spin_lock_init(&dev->slock); 456 457 /* init dma queue */ 458 INIT_LIST_HEAD(&dev->mpegq.active); | 348 spin_unlock(&dev->slock); 349 } 350} 351 352#define MAX_IRQ_LOOP 10 353 354static irqreturn_t cx8802_irq(int irq, void *dev_id) 355{ --- 50 unchanged lines hidden (view full) --- 406 pci_name(dev->pci), dev->pci_rev, dev->pci->irq, 407 dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0)); 408 409 /* initialize driver struct */ 410 spin_lock_init(&dev->slock); 411 412 /* init dma queue */ 413 INIT_LIST_HEAD(&dev->mpegq.active); |
459 dev->mpegq.timeout.function = cx8802_timeout; 460 dev->mpegq.timeout.data = (unsigned long)dev; 461 init_timer(&dev->mpegq.timeout); 462 cx88_risc_stopper(dev->pci,&dev->mpegq.stopper, 463 MO_TS_DMACNTRL,0x11,0x00); | |
464 465 /* get irq */ 466 err = request_irq(dev->pci->irq, cx8802_irq, 467 IRQF_SHARED, dev->core->name, dev); 468 if (err < 0) { 469 printk(KERN_ERR "%s: can't get IRQ %d\n", 470 dev->core->name, dev->pci->irq); 471 return err; --- 8 unchanged lines hidden (view full) --- 480static void cx8802_fini_common(struct cx8802_dev *dev) 481{ 482 dprintk( 2, "cx8802_fini_common\n" ); 483 cx8802_stop_dma(dev); 484 pci_disable_device(dev->pci); 485 486 /* unregister stuff */ 487 free_irq(dev->pci->irq, dev); | 414 415 /* get irq */ 416 err = request_irq(dev->pci->irq, cx8802_irq, 417 IRQF_SHARED, dev->core->name, dev); 418 if (err < 0) { 419 printk(KERN_ERR "%s: can't get IRQ %d\n", 420 dev->core->name, dev->pci->irq); 421 return err; --- 8 unchanged lines hidden (view full) --- 430static void cx8802_fini_common(struct cx8802_dev *dev) 431{ 432 dprintk( 2, "cx8802_fini_common\n" ); 433 cx8802_stop_dma(dev); 434 pci_disable_device(dev->pci); 435 436 /* unregister stuff */ 437 free_irq(dev->pci->irq, dev); |
488 489 /* free memory */ 490 btcx_riscmem_free(dev->pci,&dev->mpegq.stopper); | |
491} 492 493/* ----------------------------------------------------------- */ 494 495static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) 496{ 497 struct cx8802_dev *dev = pci_get_drvdata(pci_dev); 498 struct cx88_core *core = dev->core; 499 unsigned long flags; 500 501 /* stop mpeg dma */ 502 spin_lock_irqsave(&dev->slock, flags); 503 if (!list_empty(&dev->mpegq.active)) { 504 dprintk( 2, "suspend\n" ); 505 printk("%s: suspend mpeg\n", core->name); 506 cx8802_stop_dma(dev); | 438} 439 440/* ----------------------------------------------------------- */ 441 442static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) 443{ 444 struct cx8802_dev *dev = pci_get_drvdata(pci_dev); 445 struct cx88_core *core = dev->core; 446 unsigned long flags; 447 448 /* stop mpeg dma */ 449 spin_lock_irqsave(&dev->slock, flags); 450 if (!list_empty(&dev->mpegq.active)) { 451 dprintk( 2, "suspend\n" ); 452 printk("%s: suspend mpeg\n", core->name); 453 cx8802_stop_dma(dev); |
507 del_timer(&dev->mpegq.timeout); | |
508 } 509 spin_unlock_irqrestore(&dev->slock, flags); 510 511 /* FIXME -- shutdown device */ 512 cx88_shutdown(dev->core); 513 514 pci_save_state(pci_dev); 515 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { --- 351 unchanged lines hidden (view full) --- 867 .remove = cx8802_remove, 868}; 869 870module_pci_driver(cx8802_pci_driver); 871 872EXPORT_SYMBOL(cx8802_buf_prepare); 873EXPORT_SYMBOL(cx8802_buf_queue); 874EXPORT_SYMBOL(cx8802_cancel_buffers); | 454 } 455 spin_unlock_irqrestore(&dev->slock, flags); 456 457 /* FIXME -- shutdown device */ 458 cx88_shutdown(dev->core); 459 460 pci_save_state(pci_dev); 461 if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) { --- 351 unchanged lines hidden (view full) --- 813 .remove = cx8802_remove, 814}; 815 816module_pci_driver(cx8802_pci_driver); 817 818EXPORT_SYMBOL(cx8802_buf_prepare); 819EXPORT_SYMBOL(cx8802_buf_queue); 820EXPORT_SYMBOL(cx8802_cancel_buffers); |
821EXPORT_SYMBOL(cx8802_start_dma); |
|
875 876EXPORT_SYMBOL(cx8802_register_driver); 877EXPORT_SYMBOL(cx8802_unregister_driver); 878EXPORT_SYMBOL(cx8802_get_driver); 879/* ----------------------------------------------------------- */ 880/* 881 * Local variables: 882 * c-basic-offset: 8 883 * End: 884 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off 885 */ | 822 823EXPORT_SYMBOL(cx8802_register_driver); 824EXPORT_SYMBOL(cx8802_unregister_driver); 825EXPORT_SYMBOL(cx8802_get_driver); 826/* ----------------------------------------------------------- */ 827/* 828 * Local variables: 829 * c-basic-offset: 8 830 * End: 831 * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off 832 */ |