diff options
Diffstat (limited to 'drivers/media/pci/cx88')
-rw-r--r-- | drivers/media/pci/cx88/Kconfig | 5 | ||||
-rw-r--r-- | drivers/media/pci/cx88/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-alsa.c | 112 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-blackbird.c | 565 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-cards.c | 71 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-core.c | 119 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-dvb.c | 158 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-mpeg.c | 159 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-vbi.c | 216 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88-video.c | 871 | ||||
-rw-r--r-- | drivers/media/pci/cx88/cx88.h | 104 |
11 files changed, 988 insertions, 1393 deletions
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig index a63a9ad163b2..14b813d634a8 100644 --- a/drivers/media/pci/cx88/Kconfig +++ b/drivers/media/pci/cx88/Kconfig | |||
@@ -2,8 +2,7 @@ config VIDEO_CX88 | |||
2 | tristate "Conexant 2388x (bt878 successor) support" | 2 | tristate "Conexant 2388x (bt878 successor) support" |
3 | depends on VIDEO_DEV && PCI && I2C && RC_CORE | 3 | depends on VIDEO_DEV && PCI && I2C && RC_CORE |
4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
5 | select VIDEO_BTCX | 5 | select VIDEOBUF2_DMA_SG |
6 | select VIDEOBUF_DMA_SG | ||
7 | select VIDEO_TUNER | 6 | select VIDEO_TUNER |
8 | select VIDEO_TVEEPROM | 7 | select VIDEO_TVEEPROM |
9 | select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT | 8 | select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT |
@@ -45,7 +44,7 @@ config VIDEO_CX88_BLACKBIRD | |||
45 | config VIDEO_CX88_DVB | 44 | config VIDEO_CX88_DVB |
46 | tristate "DVB/ATSC Support for cx2388x based TV cards" | 45 | tristate "DVB/ATSC Support for cx2388x based TV cards" |
47 | depends on VIDEO_CX88 && DVB_CORE | 46 | depends on VIDEO_CX88 && DVB_CORE |
48 | select VIDEOBUF_DVB | 47 | select VIDEOBUF2_DVB |
49 | select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT | 48 | select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT |
50 | select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT | 49 | select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT |
51 | select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT | 50 | select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT |
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile index 8619c1becee2..d3679c3ee248 100644 --- a/drivers/media/pci/cx88/Makefile +++ b/drivers/media/pci/cx88/Makefile | |||
@@ -11,7 +11,6 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o | |||
11 | obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o | 11 | obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o |
12 | 12 | ||
13 | ccflags-y += -Idrivers/media/i2c | 13 | ccflags-y += -Idrivers/media/i2c |
14 | ccflags-y += -Idrivers/media/common | ||
15 | ccflags-y += -Idrivers/media/tuners | 14 | ccflags-y += -Idrivers/media/tuners |
16 | ccflags-y += -Idrivers/media/dvb-core | 15 | ccflags-y += -Idrivers/media/dvb-core |
17 | ccflags-y += -Idrivers/media/dvb-frontends | 16 | ccflags-y += -Idrivers/media/dvb-frontends |
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c index a72579a9f67f..7f8dc60028d5 100644 --- a/drivers/media/pci/cx88/cx88-alsa.c +++ b/drivers/media/pci/cx88/cx88-alsa.c | |||
@@ -61,8 +61,11 @@ | |||
61 | 61 | ||
62 | struct cx88_audio_buffer { | 62 | struct cx88_audio_buffer { |
63 | unsigned int bpl; | 63 | unsigned int bpl; |
64 | struct btcx_riscmem risc; | 64 | struct cx88_riscmem risc; |
65 | struct videobuf_dmabuf dma; | 65 | void *vaddr; |
66 | struct scatterlist *sglist; | ||
67 | int sglen; | ||
68 | int nr_pages; | ||
66 | }; | 69 | }; |
67 | 70 | ||
68 | struct cx88_audio_dev { | 71 | struct cx88_audio_dev { |
@@ -84,8 +87,6 @@ struct cx88_audio_dev { | |||
84 | unsigned int period_size; | 87 | unsigned int period_size; |
85 | unsigned int num_periods; | 88 | unsigned int num_periods; |
86 | 89 | ||
87 | struct videobuf_dmabuf *dma_risc; | ||
88 | |||
89 | struct cx88_audio_buffer *buf; | 90 | struct cx88_audio_buffer *buf; |
90 | 91 | ||
91 | struct snd_pcm_substream *substream; | 92 | struct snd_pcm_substream *substream; |
@@ -290,19 +291,97 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id) | |||
290 | return IRQ_RETVAL(handled); | 291 | return IRQ_RETVAL(handled); |
291 | } | 292 | } |
292 | 293 | ||
294 | static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages) | ||
295 | { | ||
296 | struct cx88_audio_buffer *buf = chip->buf; | ||
297 | struct page *pg; | ||
298 | int i; | ||
299 | |||
300 | buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); | ||
301 | if (NULL == buf->vaddr) { | ||
302 | dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); | ||
303 | return -ENOMEM; | ||
304 | } | ||
305 | |||
306 | dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", | ||
307 | (unsigned long)buf->vaddr, | ||
308 | nr_pages << PAGE_SHIFT); | ||
309 | |||
310 | memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); | ||
311 | buf->nr_pages = nr_pages; | ||
312 | |||
313 | buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); | ||
314 | if (NULL == buf->sglist) | ||
315 | goto vzalloc_err; | ||
316 | |||
317 | sg_init_table(buf->sglist, buf->nr_pages); | ||
318 | for (i = 0; i < buf->nr_pages; i++) { | ||
319 | pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); | ||
320 | if (NULL == pg) | ||
321 | goto vmalloc_to_page_err; | ||
322 | sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); | ||
323 | } | ||
324 | return 0; | ||
325 | |||
326 | vmalloc_to_page_err: | ||
327 | vfree(buf->sglist); | ||
328 | buf->sglist = NULL; | ||
329 | vzalloc_err: | ||
330 | vfree(buf->vaddr); | ||
331 | buf->vaddr = NULL; | ||
332 | return -ENOMEM; | ||
333 | } | ||
334 | |||
335 | static int cx88_alsa_dma_map(struct cx88_audio_dev *dev) | ||
336 | { | ||
337 | struct cx88_audio_buffer *buf = dev->buf; | ||
338 | |||
339 | buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist, | ||
340 | buf->nr_pages, PCI_DMA_FROMDEVICE); | ||
341 | |||
342 | if (0 == buf->sglen) { | ||
343 | pr_warn("%s: cx88_alsa_map_sg failed\n", __func__); | ||
344 | return -ENOMEM; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev) | ||
350 | { | ||
351 | struct cx88_audio_buffer *buf = dev->buf; | ||
352 | |||
353 | if (!buf->sglen) | ||
354 | return 0; | ||
355 | |||
356 | dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE); | ||
357 | buf->sglen = 0; | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf) | ||
362 | { | ||
363 | vfree(buf->sglist); | ||
364 | buf->sglist = NULL; | ||
365 | vfree(buf->vaddr); | ||
366 | buf->vaddr = NULL; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
293 | 370 | ||
294 | static int dsp_buffer_free(snd_cx88_card_t *chip) | 371 | static int dsp_buffer_free(snd_cx88_card_t *chip) |
295 | { | 372 | { |
373 | struct cx88_riscmem *risc = &chip->buf->risc; | ||
374 | |||
296 | BUG_ON(!chip->dma_size); | 375 | BUG_ON(!chip->dma_size); |
297 | 376 | ||
298 | dprintk(2,"Freeing buffer\n"); | 377 | dprintk(2,"Freeing buffer\n"); |
299 | videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); | 378 | cx88_alsa_dma_unmap(chip); |
300 | videobuf_dma_free(chip->dma_risc); | 379 | cx88_alsa_dma_free(chip->buf); |
301 | btcx_riscmem_free(chip->pci,&chip->buf->risc); | 380 | if (risc->cpu) |
381 | pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma); | ||
302 | kfree(chip->buf); | 382 | kfree(chip->buf); |
303 | 383 | ||
304 | chip->dma_risc = NULL; | 384 | chip->buf = NULL; |
305 | chip->dma_size = 0; | ||
306 | 385 | ||
307 | return 0; | 386 | return 0; |
308 | } | 387 | } |
@@ -387,7 +466,6 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
387 | struct snd_pcm_hw_params * hw_params) | 466 | struct snd_pcm_hw_params * hw_params) |
388 | { | 467 | { |
389 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 468 | snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); |
390 | struct videobuf_dmabuf *dma; | ||
391 | 469 | ||
392 | struct cx88_audio_buffer *buf; | 470 | struct cx88_audio_buffer *buf; |
393 | int ret; | 471 | int ret; |
@@ -408,20 +486,19 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
408 | if (NULL == buf) | 486 | if (NULL == buf) |
409 | return -ENOMEM; | 487 | return -ENOMEM; |
410 | 488 | ||
489 | chip->buf = buf; | ||
411 | buf->bpl = chip->period_size; | 490 | buf->bpl = chip->period_size; |
412 | 491 | ||
413 | dma = &buf->dma; | 492 | ret = cx88_alsa_dma_init(chip, |
414 | videobuf_dma_init(dma); | ||
415 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, | ||
416 | (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); | 493 | (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); |
417 | if (ret < 0) | 494 | if (ret < 0) |
418 | goto error; | 495 | goto error; |
419 | 496 | ||
420 | ret = videobuf_dma_map(&chip->pci->dev, dma); | 497 | ret = cx88_alsa_dma_map(chip); |
421 | if (ret < 0) | 498 | if (ret < 0) |
422 | goto error; | 499 | goto error; |
423 | 500 | ||
424 | ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, | 501 | ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist, |
425 | chip->period_size, chip->num_periods, 1); | 502 | chip->period_size, chip->num_periods, 1); |
426 | if (ret < 0) | 503 | if (ret < 0) |
427 | goto error; | 504 | goto error; |
@@ -430,10 +507,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream, | |||
430 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); | 507 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); |
431 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 508 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
432 | 509 | ||
433 | chip->buf = buf; | 510 | substream->runtime->dma_area = chip->buf->vaddr; |
434 | chip->dma_risc = dma; | ||
435 | |||
436 | substream->runtime->dma_area = chip->dma_risc->vaddr; | ||
437 | substream->runtime->dma_bytes = chip->dma_size; | 511 | substream->runtime->dma_bytes = chip->dma_size; |
438 | substream->runtime->dma_addr = 0; | 512 | substream->runtime->dma_addr = 0; |
439 | return 0; | 513 | return 0; |
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 150bb76e7839..4160ca4e5413 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c | |||
@@ -45,10 +45,6 @@ MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE | |||
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | MODULE_VERSION(CX88_VERSION); | 46 | MODULE_VERSION(CX88_VERSION); |
47 | 47 | ||
48 | static unsigned int mpegbufs = 32; | ||
49 | module_param(mpegbufs,int,0644); | ||
50 | MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); | ||
51 | |||
52 | static unsigned int debug; | 48 | static unsigned int debug; |
53 | module_param(debug,int,0644); | 49 | module_param(debug,int,0644); |
54 | MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); | 50 | MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); |
@@ -326,13 +322,13 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat | |||
326 | memory_read(dev->core, dev->mailbox - 4, &value); | 322 | memory_read(dev->core, dev->mailbox - 4, &value); |
327 | if (value != 0x12345678) { | 323 | if (value != 0x12345678) { |
328 | dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); | 324 | dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); |
329 | return -1; | 325 | return -EIO; |
330 | } | 326 | } |
331 | 327 | ||
332 | memory_read(dev->core, dev->mailbox, &flag); | 328 | memory_read(dev->core, dev->mailbox, &flag); |
333 | if (flag) { | 329 | if (flag) { |
334 | dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); | 330 | dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); |
335 | return -1; | 331 | return -EIO; |
336 | } | 332 | } |
337 | 333 | ||
338 | flag |= 1; /* tell 'em we're working on it */ | 334 | flag |= 1; /* tell 'em we're working on it */ |
@@ -352,14 +348,14 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat | |||
352 | memory_write(dev->core, dev->mailbox, flag); | 348 | memory_write(dev->core, dev->mailbox, flag); |
353 | 349 | ||
354 | /* wait for firmware to handle the API command */ | 350 | /* wait for firmware to handle the API command */ |
355 | timeout = jiffies + msecs_to_jiffies(10); | 351 | timeout = jiffies + msecs_to_jiffies(1000); |
356 | for (;;) { | 352 | for (;;) { |
357 | memory_read(dev->core, dev->mailbox, &flag); | 353 | memory_read(dev->core, dev->mailbox, &flag); |
358 | if (0 != (flag & 4)) | 354 | if (0 != (flag & 4)) |
359 | break; | 355 | break; |
360 | if (time_after(jiffies,timeout)) { | 356 | if (time_after(jiffies,timeout)) { |
361 | dprintk(0, "ERROR: API Mailbox timeout\n"); | 357 | dprintk(0, "ERROR: API Mailbox timeout %x\n", command); |
362 | return -1; | 358 | return -EIO; |
363 | } | 359 | } |
364 | udelay(10); | 360 | udelay(10); |
365 | } | 361 | } |
@@ -420,7 +416,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev) | |||
420 | } | 416 | } |
421 | } | 417 | } |
422 | dprintk(0, "Mailbox signature values not found!\n"); | 418 | dprintk(0, "Mailbox signature values not found!\n"); |
423 | return -1; | 419 | return -EIO; |
424 | } | 420 | } |
425 | 421 | ||
426 | static int blackbird_load_firmware(struct cx8802_dev *dev) | 422 | static int blackbird_load_firmware(struct cx8802_dev *dev) |
@@ -432,7 +428,7 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
432 | int i, retval = 0; | 428 | int i, retval = 0; |
433 | u32 value = 0; | 429 | u32 value = 0; |
434 | u32 checksum = 0; | 430 | u32 checksum = 0; |
435 | u32 *dataptr; | 431 | __le32 *dataptr; |
436 | 432 | ||
437 | retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); | 433 | retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); |
438 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); | 434 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); |
@@ -449,29 +445,28 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
449 | 445 | ||
450 | 446 | ||
451 | if (retval != 0) { | 447 | if (retval != 0) { |
452 | dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", | 448 | pr_err("Hotplug firmware request failed (%s).\n", |
453 | CX2341X_FIRM_ENC_FILENAME); | 449 | CX2341X_FIRM_ENC_FILENAME); |
454 | dprintk(0, "Please fix your hotplug setup, the board will " | 450 | pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n"); |
455 | "not work without firmware loaded!\n"); | 451 | return -EIO; |
456 | return -1; | ||
457 | } | 452 | } |
458 | 453 | ||
459 | if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { | 454 | if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { |
460 | dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", | 455 | pr_err("Firmware size mismatch (have %zd, expected %d)\n", |
461 | firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); | 456 | firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); |
462 | release_firmware(firmware); | 457 | release_firmware(firmware); |
463 | return -1; | 458 | return -EINVAL; |
464 | } | 459 | } |
465 | 460 | ||
466 | if (0 != memcmp(firmware->data, magic, 8)) { | 461 | if (0 != memcmp(firmware->data, magic, 8)) { |
467 | dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); | 462 | pr_err("Firmware magic mismatch, wrong file?\n"); |
468 | release_firmware(firmware); | 463 | release_firmware(firmware); |
469 | return -1; | 464 | return -EINVAL; |
470 | } | 465 | } |
471 | 466 | ||
472 | /* transfer to the chip */ | 467 | /* transfer to the chip */ |
473 | dprintk(1,"Loading firmware ...\n"); | 468 | dprintk(1,"Loading firmware ...\n"); |
474 | dataptr = (u32*)firmware->data; | 469 | dataptr = (__le32 *)firmware->data; |
475 | for (i = 0; i < (firmware->size >> 2); i++) { | 470 | for (i = 0; i < (firmware->size >> 2); i++) { |
476 | value = le32_to_cpu(*dataptr); | 471 | value = le32_to_cpu(*dataptr); |
477 | checksum += ~value; | 472 | checksum += ~value; |
@@ -484,12 +479,11 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
484 | memory_read(dev->core, i, &value); | 479 | memory_read(dev->core, i, &value); |
485 | checksum -= ~value; | 480 | checksum -= ~value; |
486 | } | 481 | } |
482 | release_firmware(firmware); | ||
487 | if (checksum) { | 483 | if (checksum) { |
488 | dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n"); | 484 | pr_err("Firmware load might have failed (checksum mismatch).\n"); |
489 | release_firmware(firmware); | 485 | return -EIO; |
490 | return -1; | ||
491 | } | 486 | } |
492 | release_firmware(firmware); | ||
493 | dprintk(0, "Firmware upload successful.\n"); | 487 | dprintk(0, "Firmware upload successful.\n"); |
494 | 488 | ||
495 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); | 489 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); |
@@ -521,12 +515,14 @@ DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | M | |||
521 | 515 | ||
522 | static void blackbird_codec_settings(struct cx8802_dev *dev) | 516 | static void blackbird_codec_settings(struct cx8802_dev *dev) |
523 | { | 517 | { |
518 | struct cx88_core *core = dev->core; | ||
519 | |||
524 | /* assign frame size */ | 520 | /* assign frame size */ |
525 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 521 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
526 | dev->height, dev->width); | 522 | core->height, core->width); |
527 | 523 | ||
528 | dev->cxhdl.width = dev->width; | 524 | dev->cxhdl.width = core->width; |
529 | dev->cxhdl.height = dev->height; | 525 | dev->cxhdl.height = core->height; |
530 | cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50); | 526 | cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50); |
531 | cx2341x_handler_setup(&dev->cxhdl); | 527 | cx2341x_handler_setup(&dev->cxhdl); |
532 | } | 528 | } |
@@ -540,9 +536,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
540 | dprintk(1,"Initialize codec\n"); | 536 | dprintk(1,"Initialize codec\n"); |
541 | retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ | 537 | retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ |
542 | if (retval < 0) { | 538 | if (retval < 0) { |
543 | |||
544 | dev->mpeg_active = 0; | ||
545 | |||
546 | /* ping was not successful, reset and upload firmware */ | 539 | /* ping was not successful, reset and upload firmware */ |
547 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ | 540 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ |
548 | cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ | 541 | cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ |
@@ -589,9 +582,8 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
589 | return 0; | 582 | return 0; |
590 | } | 583 | } |
591 | 584 | ||
592 | static int blackbird_start_codec(struct file *file, void *priv) | 585 | static int blackbird_start_codec(struct cx8802_dev *dev) |
593 | { | 586 | { |
594 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
595 | struct cx88_core *core = dev->core; | 587 | struct cx88_core *core = dev->core; |
596 | /* start capturing to the host interface */ | 588 | /* start capturing to the host interface */ |
597 | u32 reg; | 589 | u32 reg; |
@@ -627,7 +619,6 @@ static int blackbird_start_codec(struct file *file, void *priv) | |||
627 | BLACKBIRD_RAW_BITS_NONE | 619 | BLACKBIRD_RAW_BITS_NONE |
628 | ); | 620 | ); |
629 | 621 | ||
630 | dev->mpeg_active = 1; | ||
631 | return 0; | 622 | return 0; |
632 | } | 623 | } |
633 | 624 | ||
@@ -641,51 +632,139 @@ static int blackbird_stop_codec(struct cx8802_dev *dev) | |||
641 | 632 | ||
642 | cx2341x_handler_set_busy(&dev->cxhdl, 0); | 633 | cx2341x_handler_set_busy(&dev->cxhdl, 0); |
643 | 634 | ||
644 | dev->mpeg_active = 0; | ||
645 | return 0; | 635 | return 0; |
646 | } | 636 | } |
647 | 637 | ||
648 | /* ------------------------------------------------------------------ */ | 638 | /* ------------------------------------------------------------------ */ |
649 | 639 | ||
650 | static int bb_buf_setup(struct videobuf_queue *q, | 640 | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
651 | unsigned int *count, unsigned int *size) | 641 | unsigned int *num_buffers, unsigned int *num_planes, |
642 | unsigned int sizes[], void *alloc_ctxs[]) | ||
652 | { | 643 | { |
653 | struct cx8802_fh *fh = q->priv_data; | 644 | struct cx8802_dev *dev = q->drv_priv; |
654 | |||
655 | fh->dev->ts_packet_size = 188 * 4; /* was: 512 */ | ||
656 | fh->dev->ts_packet_count = mpegbufs; /* was: 100 */ | ||
657 | 645 | ||
658 | *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; | 646 | *num_planes = 1; |
659 | *count = fh->dev->ts_packet_count; | 647 | dev->ts_packet_size = 188 * 4; |
648 | dev->ts_packet_count = 32; | ||
649 | sizes[0] = dev->ts_packet_size * dev->ts_packet_count; | ||
660 | return 0; | 650 | return 0; |
661 | } | 651 | } |
662 | 652 | ||
663 | static int | 653 | static int buffer_prepare(struct vb2_buffer *vb) |
664 | bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
665 | enum v4l2_field field) | ||
666 | { | 654 | { |
667 | struct cx8802_fh *fh = q->priv_data; | 655 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
668 | return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field); | 656 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
657 | |||
658 | return cx8802_buf_prepare(vb->vb2_queue, dev, buf); | ||
669 | } | 659 | } |
670 | 660 | ||
671 | static void | 661 | static void buffer_finish(struct vb2_buffer *vb) |
672 | bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
673 | { | 662 | { |
674 | struct cx8802_fh *fh = q->priv_data; | 663 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
675 | cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb); | 664 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
665 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||
666 | struct cx88_riscmem *risc = &buf->risc; | ||
667 | |||
668 | if (risc->cpu) | ||
669 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); | ||
670 | memset(risc, 0, sizeof(*risc)); | ||
671 | |||
672 | dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); | ||
676 | } | 673 | } |
677 | 674 | ||
678 | static void | 675 | static void buffer_queue(struct vb2_buffer *vb) |
679 | bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
680 | { | 676 | { |
681 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | 677 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
678 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
679 | |||
680 | cx8802_buf_queue(dev, buf); | ||
681 | } | ||
682 | |||
683 | static int start_streaming(struct vb2_queue *q, unsigned int count) | ||
684 | { | ||
685 | struct cx8802_dev *dev = q->drv_priv; | ||
686 | struct cx88_dmaqueue *dmaq = &dev->mpegq; | ||
687 | struct cx8802_driver *drv; | ||
688 | struct cx88_buffer *buf; | ||
689 | unsigned long flags; | ||
690 | int err; | ||
691 | |||
692 | /* Make sure we can acquire the hardware */ | ||
693 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
694 | if (!drv) { | ||
695 | dprintk(1, "%s: blackbird driver is not loaded\n", __func__); | ||
696 | err = -ENODEV; | ||
697 | goto fail; | ||
698 | } | ||
699 | |||
700 | err = drv->request_acquire(drv); | ||
701 | if (err != 0) { | ||
702 | dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__, err); | ||
703 | goto fail; | ||
704 | } | ||
705 | |||
706 | if (blackbird_initialize_codec(dev) < 0) { | ||
707 | drv->request_release(drv); | ||
708 | err = -EINVAL; | ||
709 | goto fail; | ||
710 | } | ||
711 | |||
712 | err = blackbird_start_codec(dev); | ||
713 | if (err == 0) { | ||
714 | buf = list_entry(dmaq->active.next, struct cx88_buffer, list); | ||
715 | cx8802_start_dma(dev, dmaq, buf); | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | fail: | ||
720 | spin_lock_irqsave(&dev->slock, flags); | ||
721 | while (!list_empty(&dmaq->active)) { | ||
722 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
723 | struct cx88_buffer, list); | ||
724 | |||
725 | list_del(&buf->list); | ||
726 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | ||
727 | } | ||
728 | spin_unlock_irqrestore(&dev->slock, flags); | ||
729 | return err; | ||
682 | } | 730 | } |
683 | 731 | ||
684 | static struct videobuf_queue_ops blackbird_qops = { | 732 | static void stop_streaming(struct vb2_queue *q) |
685 | .buf_setup = bb_buf_setup, | 733 | { |
686 | .buf_prepare = bb_buf_prepare, | 734 | struct cx8802_dev *dev = q->drv_priv; |
687 | .buf_queue = bb_buf_queue, | 735 | struct cx88_dmaqueue *dmaq = &dev->mpegq; |
688 | .buf_release = bb_buf_release, | 736 | struct cx8802_driver *drv = NULL; |
737 | unsigned long flags; | ||
738 | |||
739 | cx8802_cancel_buffers(dev); | ||
740 | blackbird_stop_codec(dev); | ||
741 | |||
742 | /* Make sure we release the hardware */ | ||
743 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
744 | WARN_ON(!drv); | ||
745 | if (drv) | ||
746 | drv->request_release(drv); | ||
747 | |||
748 | spin_lock_irqsave(&dev->slock, flags); | ||
749 | while (!list_empty(&dmaq->active)) { | ||
750 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
751 | struct cx88_buffer, list); | ||
752 | |||
753 | list_del(&buf->list); | ||
754 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
755 | } | ||
756 | spin_unlock_irqrestore(&dev->slock, flags); | ||
757 | } | ||
758 | |||
759 | static struct vb2_ops blackbird_qops = { | ||
760 | .queue_setup = queue_setup, | ||
761 | .buf_prepare = buffer_prepare, | ||
762 | .buf_finish = buffer_finish, | ||
763 | .buf_queue = buffer_queue, | ||
764 | .wait_prepare = vb2_ops_wait_prepare, | ||
765 | .wait_finish = vb2_ops_wait_finish, | ||
766 | .start_streaming = start_streaming, | ||
767 | .stop_streaming = stop_streaming, | ||
689 | }; | 768 | }; |
690 | 769 | ||
691 | /* ------------------------------------------------------------------ */ | 770 | /* ------------------------------------------------------------------ */ |
@@ -693,8 +772,8 @@ static struct videobuf_queue_ops blackbird_qops = { | |||
693 | static int vidioc_querycap(struct file *file, void *priv, | 772 | static int vidioc_querycap(struct file *file, void *priv, |
694 | struct v4l2_capability *cap) | 773 | struct v4l2_capability *cap) |
695 | { | 774 | { |
696 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | 775 | struct cx8802_dev *dev = video_drvdata(file); |
697 | struct cx88_core *core = dev->core; | 776 | struct cx88_core *core = dev->core; |
698 | 777 | ||
699 | strcpy(cap->driver, "cx88_blackbird"); | 778 | strcpy(cap->driver, "cx88_blackbird"); |
700 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); | 779 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); |
@@ -714,131 +793,111 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | |||
714 | return 0; | 793 | return 0; |
715 | } | 794 | } |
716 | 795 | ||
717 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | 796 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
718 | struct v4l2_format *f) | 797 | struct v4l2_format *f) |
719 | { | 798 | { |
720 | struct cx8802_fh *fh = priv; | 799 | struct cx8802_dev *dev = video_drvdata(file); |
721 | struct cx8802_dev *dev = fh->dev; | 800 | struct cx88_core *core = dev->core; |
722 | 801 | ||
723 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 802 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
724 | f->fmt.pix.bytesperline = 0; | 803 | f->fmt.pix.bytesperline = 0; |
725 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ | 804 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; |
726 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 805 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
727 | f->fmt.pix.width = dev->width; | 806 | f->fmt.pix.width = core->width; |
728 | f->fmt.pix.height = dev->height; | 807 | f->fmt.pix.height = core->height; |
729 | f->fmt.pix.field = fh->mpegq.field; | 808 | f->fmt.pix.field = core->field; |
730 | dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", | ||
731 | dev->width, dev->height, fh->mpegq.field ); | ||
732 | return 0; | 809 | return 0; |
733 | } | 810 | } |
734 | 811 | ||
735 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | 812 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
736 | struct v4l2_format *f) | 813 | struct v4l2_format *f) |
737 | { | 814 | { |
738 | struct cx8802_fh *fh = priv; | 815 | struct cx8802_dev *dev = video_drvdata(file); |
739 | struct cx8802_dev *dev = fh->dev; | 816 | struct cx88_core *core = dev->core; |
817 | unsigned maxw, maxh; | ||
818 | enum v4l2_field field; | ||
740 | 819 | ||
741 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 820 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
742 | f->fmt.pix.bytesperline = 0; | 821 | f->fmt.pix.bytesperline = 0; |
743 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ | 822 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; |
744 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 823 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
745 | dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", | 824 | |
746 | dev->width, dev->height, fh->mpegq.field ); | 825 | maxw = norm_maxw(core->tvnorm); |
826 | maxh = norm_maxh(core->tvnorm); | ||
827 | |||
828 | field = f->fmt.pix.field; | ||
829 | |||
830 | switch (field) { | ||
831 | case V4L2_FIELD_TOP: | ||
832 | case V4L2_FIELD_BOTTOM: | ||
833 | case V4L2_FIELD_INTERLACED: | ||
834 | case V4L2_FIELD_SEQ_BT: | ||
835 | case V4L2_FIELD_SEQ_TB: | ||
836 | break; | ||
837 | default: | ||
838 | field = (f->fmt.pix.height > maxh / 2) | ||
839 | ? V4L2_FIELD_INTERLACED | ||
840 | : V4L2_FIELD_BOTTOM; | ||
841 | break; | ||
842 | } | ||
843 | if (V4L2_FIELD_HAS_T_OR_B(field)) | ||
844 | maxh /= 2; | ||
845 | |||
846 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | ||
847 | &f->fmt.pix.height, 32, maxh, 0, 0); | ||
848 | f->fmt.pix.field = field; | ||
747 | return 0; | 849 | return 0; |
748 | } | 850 | } |
749 | 851 | ||
750 | static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, | 852 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
751 | struct v4l2_format *f) | 853 | struct v4l2_format *f) |
752 | { | 854 | { |
753 | struct cx8802_fh *fh = priv; | 855 | struct cx8802_dev *dev = video_drvdata(file); |
754 | struct cx8802_dev *dev = fh->dev; | ||
755 | struct cx88_core *core = dev->core; | 856 | struct cx88_core *core = dev->core; |
756 | 857 | ||
757 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 858 | if (vb2_is_busy(&dev->vb2_mpegq)) |
758 | f->fmt.pix.bytesperline = 0; | 859 | return -EBUSY; |
759 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ | 860 | if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) || |
760 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 861 | vb2_is_busy(&core->v4ldev->vb2_vbiq))) |
761 | dev->width = f->fmt.pix.width; | 862 | return -EBUSY; |
762 | dev->height = f->fmt.pix.height; | 863 | vidioc_try_fmt_vid_cap(file, priv, f); |
763 | fh->mpegq.field = f->fmt.pix.field; | 864 | core->width = f->fmt.pix.width; |
865 | core->height = f->fmt.pix.height; | ||
866 | core->field = f->fmt.pix.field; | ||
764 | cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); | 867 | cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); |
765 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 868 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
766 | f->fmt.pix.height, f->fmt.pix.width); | 869 | f->fmt.pix.height, f->fmt.pix.width); |
767 | dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", | ||
768 | f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); | ||
769 | return 0; | 870 | return 0; |
770 | } | 871 | } |
771 | 872 | ||
772 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) | ||
773 | { | ||
774 | struct cx8802_fh *fh = priv; | ||
775 | return (videobuf_reqbufs(&fh->mpegq, p)); | ||
776 | } | ||
777 | |||
778 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
779 | { | ||
780 | struct cx8802_fh *fh = priv; | ||
781 | return (videobuf_querybuf(&fh->mpegq, p)); | ||
782 | } | ||
783 | |||
784 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
785 | { | ||
786 | struct cx8802_fh *fh = priv; | ||
787 | return (videobuf_qbuf(&fh->mpegq, p)); | ||
788 | } | ||
789 | |||
790 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
791 | { | ||
792 | struct cx8802_fh *fh = priv; | ||
793 | return (videobuf_dqbuf(&fh->mpegq, p, | ||
794 | file->f_flags & O_NONBLOCK)); | ||
795 | } | ||
796 | |||
797 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
798 | { | ||
799 | struct cx8802_fh *fh = priv; | ||
800 | struct cx8802_dev *dev = fh->dev; | ||
801 | |||
802 | if (!dev->mpeg_active) | ||
803 | blackbird_start_codec(file, fh); | ||
804 | return videobuf_streamon(&fh->mpegq); | ||
805 | } | ||
806 | |||
807 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
808 | { | ||
809 | struct cx8802_fh *fh = priv; | ||
810 | struct cx8802_dev *dev = fh->dev; | ||
811 | |||
812 | if (dev->mpeg_active) | ||
813 | blackbird_stop_codec(dev); | ||
814 | return videobuf_streamoff(&fh->mpegq); | ||
815 | } | ||
816 | |||
817 | static int vidioc_s_frequency (struct file *file, void *priv, | 873 | static int vidioc_s_frequency (struct file *file, void *priv, |
818 | const struct v4l2_frequency *f) | 874 | const struct v4l2_frequency *f) |
819 | { | 875 | { |
820 | struct cx8802_fh *fh = priv; | 876 | struct cx8802_dev *dev = video_drvdata(file); |
821 | struct cx8802_dev *dev = fh->dev; | 877 | struct cx88_core *core = dev->core; |
822 | struct cx88_core *core = dev->core; | 878 | bool streaming; |
823 | 879 | ||
824 | if (unlikely(UNSET == core->board.tuner_type)) | 880 | if (unlikely(UNSET == core->board.tuner_type)) |
825 | return -EINVAL; | 881 | return -EINVAL; |
826 | if (unlikely(f->tuner != 0)) | 882 | if (unlikely(f->tuner != 0)) |
827 | return -EINVAL; | 883 | return -EINVAL; |
828 | if (dev->mpeg_active) | 884 | streaming = vb2_start_streaming_called(&dev->vb2_mpegq); |
885 | if (streaming) | ||
829 | blackbird_stop_codec(dev); | 886 | blackbird_stop_codec(dev); |
830 | 887 | ||
831 | cx88_set_freq (core,f); | 888 | cx88_set_freq (core,f); |
832 | blackbird_initialize_codec(dev); | 889 | blackbird_initialize_codec(dev); |
833 | cx88_set_scale(dev->core, dev->width, dev->height, | 890 | cx88_set_scale(core, core->width, core->height, |
834 | fh->mpegq.field); | 891 | core->field); |
892 | if (streaming) | ||
893 | blackbird_start_codec(dev); | ||
835 | return 0; | 894 | return 0; |
836 | } | 895 | } |
837 | 896 | ||
838 | static int vidioc_log_status (struct file *file, void *priv) | 897 | static int vidioc_log_status (struct file *file, void *priv) |
839 | { | 898 | { |
840 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | 899 | struct cx8802_dev *dev = video_drvdata(file); |
841 | struct cx88_core *core = dev->core; | 900 | struct cx88_core *core = dev->core; |
842 | char name[32 + 2]; | 901 | char name[32 + 2]; |
843 | 902 | ||
844 | snprintf(name, sizeof(name), "%s/2", core->name); | 903 | snprintf(name, sizeof(name), "%s/2", core->name); |
@@ -850,15 +909,16 @@ static int vidioc_log_status (struct file *file, void *priv) | |||
850 | static int vidioc_enum_input (struct file *file, void *priv, | 909 | static int vidioc_enum_input (struct file *file, void *priv, |
851 | struct v4l2_input *i) | 910 | struct v4l2_input *i) |
852 | { | 911 | { |
853 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 912 | struct cx8802_dev *dev = video_drvdata(file); |
913 | struct cx88_core *core = dev->core; | ||
854 | return cx88_enum_input (core,i); | 914 | return cx88_enum_input (core,i); |
855 | } | 915 | } |
856 | 916 | ||
857 | static int vidioc_g_frequency (struct file *file, void *priv, | 917 | static int vidioc_g_frequency (struct file *file, void *priv, |
858 | struct v4l2_frequency *f) | 918 | struct v4l2_frequency *f) |
859 | { | 919 | { |
860 | struct cx8802_fh *fh = priv; | 920 | struct cx8802_dev *dev = video_drvdata(file); |
861 | struct cx88_core *core = fh->dev->core; | 921 | struct cx88_core *core = dev->core; |
862 | 922 | ||
863 | if (unlikely(UNSET == core->board.tuner_type)) | 923 | if (unlikely(UNSET == core->board.tuner_type)) |
864 | return -EINVAL; | 924 | return -EINVAL; |
@@ -873,7 +933,8 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
873 | 933 | ||
874 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | 934 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
875 | { | 935 | { |
876 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 936 | struct cx8802_dev *dev = video_drvdata(file); |
937 | struct cx88_core *core = dev->core; | ||
877 | 938 | ||
878 | *i = core->input; | 939 | *i = core->input; |
879 | return 0; | 940 | return 0; |
@@ -881,24 +942,24 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | |||
881 | 942 | ||
882 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | 943 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
883 | { | 944 | { |
884 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 945 | struct cx8802_dev *dev = video_drvdata(file); |
946 | struct cx88_core *core = dev->core; | ||
885 | 947 | ||
886 | if (i >= 4) | 948 | if (i >= 4) |
887 | return -EINVAL; | 949 | return -EINVAL; |
888 | if (0 == INPUT(i).type) | 950 | if (0 == INPUT(i).type) |
889 | return -EINVAL; | 951 | return -EINVAL; |
890 | 952 | ||
891 | mutex_lock(&core->lock); | ||
892 | cx88_newstation(core); | 953 | cx88_newstation(core); |
893 | cx88_video_mux(core,i); | 954 | cx88_video_mux(core,i); |
894 | mutex_unlock(&core->lock); | ||
895 | return 0; | 955 | return 0; |
896 | } | 956 | } |
897 | 957 | ||
898 | static int vidioc_g_tuner (struct file *file, void *priv, | 958 | static int vidioc_g_tuner (struct file *file, void *priv, |
899 | struct v4l2_tuner *t) | 959 | struct v4l2_tuner *t) |
900 | { | 960 | { |
901 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 961 | struct cx8802_dev *dev = video_drvdata(file); |
962 | struct cx88_core *core = dev->core; | ||
902 | u32 reg; | 963 | u32 reg; |
903 | 964 | ||
904 | if (unlikely(UNSET == core->board.tuner_type)) | 965 | if (unlikely(UNSET == core->board.tuner_type)) |
@@ -920,7 +981,8 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
920 | static int vidioc_s_tuner (struct file *file, void *priv, | 981 | static int vidioc_s_tuner (struct file *file, void *priv, |
921 | const struct v4l2_tuner *t) | 982 | const struct v4l2_tuner *t) |
922 | { | 983 | { |
923 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 984 | struct cx8802_dev *dev = video_drvdata(file); |
985 | struct cx88_core *core = dev->core; | ||
924 | 986 | ||
925 | if (UNSET == core->board.tuner_type) | 987 | if (UNSET == core->board.tuner_type) |
926 | return -EINVAL; | 988 | return -EINVAL; |
@@ -933,7 +995,8 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
933 | 995 | ||
934 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | 996 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) |
935 | { | 997 | { |
936 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 998 | struct cx8802_dev *dev = video_drvdata(file); |
999 | struct cx88_core *core = dev->core; | ||
937 | 1000 | ||
938 | *tvnorm = core->tvnorm; | 1001 | *tvnorm = core->tvnorm; |
939 | return 0; | 1002 | return 0; |
@@ -941,155 +1004,20 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | |||
941 | 1004 | ||
942 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) | 1005 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) |
943 | { | 1006 | { |
944 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
945 | |||
946 | mutex_lock(&core->lock); | ||
947 | cx88_set_tvnorm(core, id); | ||
948 | mutex_unlock(&core->lock); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | /* FIXME: cx88_ioctl_hook not implemented */ | ||
953 | |||
954 | static int mpeg_open(struct file *file) | ||
955 | { | ||
956 | struct video_device *vdev = video_devdata(file); | ||
957 | struct cx8802_dev *dev = video_drvdata(file); | 1007 | struct cx8802_dev *dev = video_drvdata(file); |
958 | struct cx8802_fh *fh; | 1008 | struct cx88_core *core = dev->core; |
959 | struct cx8802_driver *drv = NULL; | ||
960 | int err; | ||
961 | |||
962 | dprintk( 1, "%s\n", __func__); | ||
963 | |||
964 | mutex_lock(&dev->core->lock); | ||
965 | |||
966 | /* Make sure we can acquire the hardware */ | ||
967 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
968 | if (!drv) { | ||
969 | dprintk(1, "%s: blackbird driver is not loaded\n", __func__); | ||
970 | mutex_unlock(&dev->core->lock); | ||
971 | return -ENODEV; | ||
972 | } | ||
973 | |||
974 | err = drv->request_acquire(drv); | ||
975 | if (err != 0) { | ||
976 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); | ||
977 | mutex_unlock(&dev->core->lock); | ||
978 | return err; | ||
979 | } | ||
980 | |||
981 | if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) { | ||
982 | drv->request_release(drv); | ||
983 | mutex_unlock(&dev->core->lock); | ||
984 | return -EINVAL; | ||
985 | } | ||
986 | dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); | ||
987 | |||
988 | /* allocate + initialize per filehandle data */ | ||
989 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | ||
990 | if (NULL == fh) { | ||
991 | drv->request_release(drv); | ||
992 | mutex_unlock(&dev->core->lock); | ||
993 | return -ENOMEM; | ||
994 | } | ||
995 | v4l2_fh_init(&fh->fh, vdev); | ||
996 | file->private_data = fh; | ||
997 | fh->dev = dev; | ||
998 | |||
999 | videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops, | ||
1000 | &dev->pci->dev, &dev->slock, | ||
1001 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1002 | V4L2_FIELD_INTERLACED, | ||
1003 | sizeof(struct cx88_buffer), | ||
1004 | fh, NULL); | ||
1005 | |||
1006 | /* FIXME: locking against other video device */ | ||
1007 | cx88_set_scale(dev->core, dev->width, dev->height, | ||
1008 | fh->mpegq.field); | ||
1009 | |||
1010 | dev->core->mpeg_users++; | ||
1011 | mutex_unlock(&dev->core->lock); | ||
1012 | v4l2_fh_add(&fh->fh); | ||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int mpeg_release(struct file *file) | ||
1017 | { | ||
1018 | struct cx8802_fh *fh = file->private_data; | ||
1019 | struct cx8802_dev *dev = fh->dev; | ||
1020 | struct cx8802_driver *drv = NULL; | ||
1021 | |||
1022 | mutex_lock(&dev->core->lock); | ||
1023 | |||
1024 | if (dev->mpeg_active && dev->core->mpeg_users == 1) | ||
1025 | blackbird_stop_codec(dev); | ||
1026 | |||
1027 | cx8802_cancel_buffers(fh->dev); | ||
1028 | /* stop mpeg capture */ | ||
1029 | videobuf_stop(&fh->mpegq); | ||
1030 | |||
1031 | videobuf_mmap_free(&fh->mpegq); | ||
1032 | |||
1033 | v4l2_fh_del(&fh->fh); | ||
1034 | v4l2_fh_exit(&fh->fh); | ||
1035 | file->private_data = NULL; | ||
1036 | kfree(fh); | ||
1037 | |||
1038 | /* Make sure we release the hardware */ | ||
1039 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
1040 | WARN_ON(!drv); | ||
1041 | if (drv) | ||
1042 | drv->request_release(drv); | ||
1043 | |||
1044 | dev->core->mpeg_users--; | ||
1045 | |||
1046 | mutex_unlock(&dev->core->lock); | ||
1047 | |||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | static ssize_t | ||
1052 | mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
1053 | { | ||
1054 | struct cx8802_fh *fh = file->private_data; | ||
1055 | struct cx8802_dev *dev = fh->dev; | ||
1056 | |||
1057 | if (!dev->mpeg_active) | ||
1058 | blackbird_start_codec(file, fh); | ||
1059 | |||
1060 | return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, | ||
1061 | file->f_flags & O_NONBLOCK); | ||
1062 | } | ||
1063 | |||
1064 | static unsigned int | ||
1065 | mpeg_poll(struct file *file, struct poll_table_struct *wait) | ||
1066 | { | ||
1067 | unsigned long req_events = poll_requested_events(wait); | ||
1068 | struct cx8802_fh *fh = file->private_data; | ||
1069 | struct cx8802_dev *dev = fh->dev; | ||
1070 | |||
1071 | if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM))) | ||
1072 | blackbird_start_codec(file, fh); | ||
1073 | |||
1074 | return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait); | ||
1075 | } | ||
1076 | |||
1077 | static int | ||
1078 | mpeg_mmap(struct file *file, struct vm_area_struct * vma) | ||
1079 | { | ||
1080 | struct cx8802_fh *fh = file->private_data; | ||
1081 | 1009 | ||
1082 | return videobuf_mmap_mapper(&fh->mpegq, vma); | 1010 | return cx88_set_tvnorm(core, id); |
1083 | } | 1011 | } |
1084 | 1012 | ||
1085 | static const struct v4l2_file_operations mpeg_fops = | 1013 | static const struct v4l2_file_operations mpeg_fops = |
1086 | { | 1014 | { |
1087 | .owner = THIS_MODULE, | 1015 | .owner = THIS_MODULE, |
1088 | .open = mpeg_open, | 1016 | .open = v4l2_fh_open, |
1089 | .release = mpeg_release, | 1017 | .release = vb2_fop_release, |
1090 | .read = mpeg_read, | 1018 | .read = vb2_fop_read, |
1091 | .poll = mpeg_poll, | 1019 | .poll = vb2_fop_poll, |
1092 | .mmap = mpeg_mmap, | 1020 | .mmap = vb2_fop_mmap, |
1093 | .unlocked_ioctl = video_ioctl2, | 1021 | .unlocked_ioctl = video_ioctl2, |
1094 | }; | 1022 | }; |
1095 | 1023 | ||
@@ -1099,12 +1027,12 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1099 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1027 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1100 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 1028 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1101 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1029 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1102 | .vidioc_reqbufs = vidioc_reqbufs, | 1030 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1103 | .vidioc_querybuf = vidioc_querybuf, | 1031 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1104 | .vidioc_qbuf = vidioc_qbuf, | 1032 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1105 | .vidioc_dqbuf = vidioc_dqbuf, | 1033 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1106 | .vidioc_streamon = vidioc_streamon, | 1034 | .vidioc_streamon = vb2_ioctl_streamon, |
1107 | .vidioc_streamoff = vidioc_streamoff, | 1035 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1108 | .vidioc_s_frequency = vidioc_s_frequency, | 1036 | .vidioc_s_frequency = vidioc_s_frequency, |
1109 | .vidioc_log_status = vidioc_log_status, | 1037 | .vidioc_log_status = vidioc_log_status, |
1110 | .vidioc_enum_input = vidioc_enum_input, | 1038 | .vidioc_enum_input = vidioc_enum_input, |
@@ -1189,11 +1117,12 @@ static int blackbird_register_video(struct cx8802_dev *dev) | |||
1189 | { | 1117 | { |
1190 | int err; | 1118 | int err; |
1191 | 1119 | ||
1192 | dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, | 1120 | dev->mpeg_dev = cx88_vdev_init(dev->core, dev->pci, |
1193 | &cx8802_mpeg_template,"mpeg"); | 1121 | &cx8802_mpeg_template, "mpeg"); |
1194 | dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl; | 1122 | dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl; |
1195 | video_set_drvdata(dev->mpeg_dev, dev); | 1123 | video_set_drvdata(dev->mpeg_dev, dev); |
1196 | err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); | 1124 | dev->mpeg_dev->queue = &dev->vb2_mpegq; |
1125 | err = video_register_device(dev->mpeg_dev, VFL_TYPE_GRABBER, -1); | ||
1197 | if (err < 0) { | 1126 | if (err < 0) { |
1198 | printk(KERN_INFO "%s/2: can't register mpeg device\n", | 1127 | printk(KERN_INFO "%s/2: can't register mpeg device\n", |
1199 | dev->core->name); | 1128 | dev->core->name); |
@@ -1210,6 +1139,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1210 | { | 1139 | { |
1211 | struct cx88_core *core = drv->core; | 1140 | struct cx88_core *core = drv->core; |
1212 | struct cx8802_dev *dev = core->dvbdev; | 1141 | struct cx8802_dev *dev = core->dvbdev; |
1142 | struct vb2_queue *q; | ||
1213 | int err; | 1143 | int err; |
1214 | 1144 | ||
1215 | dprintk( 1, "%s\n", __func__); | 1145 | dprintk( 1, "%s\n", __func__); |
@@ -1223,15 +1153,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1223 | if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) | 1153 | if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) |
1224 | goto fail_core; | 1154 | goto fail_core; |
1225 | 1155 | ||
1226 | dev->width = 720; | ||
1227 | if (core->tvnorm & V4L2_STD_525_60) { | ||
1228 | dev->height = 480; | ||
1229 | } else { | ||
1230 | dev->height = 576; | ||
1231 | } | ||
1232 | dev->cxhdl.port = CX2341X_PORT_STREAMING; | 1156 | dev->cxhdl.port = CX2341X_PORT_STREAMING; |
1233 | dev->cxhdl.width = dev->width; | 1157 | dev->cxhdl.width = core->width; |
1234 | dev->cxhdl.height = dev->height; | 1158 | dev->cxhdl.height = core->height; |
1235 | dev->cxhdl.func = blackbird_mbox_func; | 1159 | dev->cxhdl.func = blackbird_mbox_func; |
1236 | dev->cxhdl.priv = dev; | 1160 | dev->cxhdl.priv = dev; |
1237 | err = cx2341x_handler_init(&dev->cxhdl, 36); | 1161 | err = cx2341x_handler_init(&dev->cxhdl, 36); |
@@ -1250,13 +1174,30 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1250 | // init_controls(core); | 1174 | // init_controls(core); |
1251 | cx88_set_tvnorm(core,core->tvnorm); | 1175 | cx88_set_tvnorm(core,core->tvnorm); |
1252 | cx88_video_mux(core,0); | 1176 | cx88_video_mux(core,0); |
1253 | cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576); | 1177 | cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576); |
1254 | cx2341x_handler_setup(&dev->cxhdl); | 1178 | cx2341x_handler_setup(&dev->cxhdl); |
1179 | |||
1180 | q = &dev->vb2_mpegq; | ||
1181 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1182 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||
1183 | q->gfp_flags = GFP_DMA32; | ||
1184 | q->min_buffers_needed = 2; | ||
1185 | q->drv_priv = dev; | ||
1186 | q->buf_struct_size = sizeof(struct cx88_buffer); | ||
1187 | q->ops = &blackbird_qops; | ||
1188 | q->mem_ops = &vb2_dma_sg_memops; | ||
1189 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1190 | q->lock = &core->lock; | ||
1191 | |||
1192 | err = vb2_queue_init(q); | ||
1193 | if (err < 0) | ||
1194 | goto fail_core; | ||
1195 | |||
1255 | blackbird_register_video(dev); | 1196 | blackbird_register_video(dev); |
1256 | 1197 | ||
1257 | return 0; | 1198 | return 0; |
1258 | 1199 | ||
1259 | fail_core: | 1200 | fail_core: |
1260 | return err; | 1201 | return err; |
1261 | } | 1202 | } |
1262 | 1203 | ||
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index 851754bf1291..8f2556ec3971 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c | |||
@@ -347,7 +347,7 @@ static const struct cx88_board cx88_boards[] = { | |||
347 | }, | 347 | }, |
348 | [CX88_BOARD_IODATA_GVVCP3PCI] = { | 348 | [CX88_BOARD_IODATA_GVVCP3PCI] = { |
349 | .name = "IODATA GV-VCP3/PCI", | 349 | .name = "IODATA GV-VCP3/PCI", |
350 | .tuner_type = TUNER_ABSENT, | 350 | .tuner_type = UNSET, |
351 | .radio_type = UNSET, | 351 | .radio_type = UNSET, |
352 | .tuner_addr = ADDR_UNSET, | 352 | .tuner_addr = ADDR_UNSET, |
353 | .radio_addr = ADDR_UNSET, | 353 | .radio_addr = ADDR_UNSET, |
@@ -436,7 +436,7 @@ static const struct cx88_board cx88_boards[] = { | |||
436 | }, | 436 | }, |
437 | [CX88_BOARD_KWORLD_DVB_T] = { | 437 | [CX88_BOARD_KWORLD_DVB_T] = { |
438 | .name = "KWorld/VStream XPert DVB-T", | 438 | .name = "KWorld/VStream XPert DVB-T", |
439 | .tuner_type = TUNER_ABSENT, | 439 | .tuner_type = UNSET, |
440 | .radio_type = UNSET, | 440 | .radio_type = UNSET, |
441 | .tuner_addr = ADDR_UNSET, | 441 | .tuner_addr = ADDR_UNSET, |
442 | .radio_addr = ADDR_UNSET, | 442 | .radio_addr = ADDR_UNSET, |
@@ -455,7 +455,7 @@ static const struct cx88_board cx88_boards[] = { | |||
455 | }, | 455 | }, |
456 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { | 456 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { |
457 | .name = "DViCO FusionHDTV DVB-T1", | 457 | .name = "DViCO FusionHDTV DVB-T1", |
458 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ | 458 | .tuner_type = UNSET, /* No analog tuner */ |
459 | .radio_type = UNSET, | 459 | .radio_type = UNSET, |
460 | .tuner_addr = ADDR_UNSET, | 460 | .tuner_addr = ADDR_UNSET, |
461 | .radio_addr = ADDR_UNSET, | 461 | .radio_addr = ADDR_UNSET, |
@@ -542,7 +542,7 @@ static const struct cx88_board cx88_boards[] = { | |||
542 | }, | 542 | }, |
543 | [CX88_BOARD_HAUPPAUGE_DVB_T1] = { | 543 | [CX88_BOARD_HAUPPAUGE_DVB_T1] = { |
544 | .name = "Hauppauge Nova-T DVB-T", | 544 | .name = "Hauppauge Nova-T DVB-T", |
545 | .tuner_type = TUNER_ABSENT, | 545 | .tuner_type = UNSET, |
546 | .radio_type = UNSET, | 546 | .radio_type = UNSET, |
547 | .tuner_addr = ADDR_UNSET, | 547 | .tuner_addr = ADDR_UNSET, |
548 | .radio_addr = ADDR_UNSET, | 548 | .radio_addr = ADDR_UNSET, |
@@ -554,7 +554,7 @@ static const struct cx88_board cx88_boards[] = { | |||
554 | }, | 554 | }, |
555 | [CX88_BOARD_CONEXANT_DVB_T1] = { | 555 | [CX88_BOARD_CONEXANT_DVB_T1] = { |
556 | .name = "Conexant DVB-T reference design", | 556 | .name = "Conexant DVB-T reference design", |
557 | .tuner_type = TUNER_ABSENT, | 557 | .tuner_type = UNSET, |
558 | .radio_type = UNSET, | 558 | .radio_type = UNSET, |
559 | .tuner_addr = ADDR_UNSET, | 559 | .tuner_addr = ADDR_UNSET, |
560 | .radio_addr = ADDR_UNSET, | 560 | .radio_addr = ADDR_UNSET, |
@@ -579,7 +579,7 @@ static const struct cx88_board cx88_boards[] = { | |||
579 | }, | 579 | }, |
580 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { | 580 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = { |
581 | .name = "DViCO FusionHDTV DVB-T Plus", | 581 | .name = "DViCO FusionHDTV DVB-T Plus", |
582 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ | 582 | .tuner_type = UNSET, /* No analog tuner */ |
583 | .radio_type = UNSET, | 583 | .radio_type = UNSET, |
584 | .tuner_addr = ADDR_UNSET, | 584 | .tuner_addr = ADDR_UNSET, |
585 | .radio_addr = ADDR_UNSET, | 585 | .radio_addr = ADDR_UNSET, |
@@ -596,7 +596,7 @@ static const struct cx88_board cx88_boards[] = { | |||
596 | }, | 596 | }, |
597 | [CX88_BOARD_DNTV_LIVE_DVB_T] = { | 597 | [CX88_BOARD_DNTV_LIVE_DVB_T] = { |
598 | .name = "digitalnow DNTV Live! DVB-T", | 598 | .name = "digitalnow DNTV Live! DVB-T", |
599 | .tuner_type = TUNER_ABSENT, | 599 | .tuner_type = UNSET, |
600 | .radio_type = UNSET, | 600 | .radio_type = UNSET, |
601 | .tuner_addr = ADDR_UNSET, | 601 | .tuner_addr = ADDR_UNSET, |
602 | .radio_addr = ADDR_UNSET, | 602 | .radio_addr = ADDR_UNSET, |
@@ -787,7 +787,7 @@ static const struct cx88_board cx88_boards[] = { | |||
787 | }, | 787 | }, |
788 | [CX88_BOARD_ADSTECH_DVB_T_PCI] = { | 788 | [CX88_BOARD_ADSTECH_DVB_T_PCI] = { |
789 | .name = "ADS Tech Instant TV DVB-T PCI", | 789 | .name = "ADS Tech Instant TV DVB-T PCI", |
790 | .tuner_type = TUNER_ABSENT, | 790 | .tuner_type = UNSET, |
791 | .radio_type = UNSET, | 791 | .radio_type = UNSET, |
792 | .tuner_addr = ADDR_UNSET, | 792 | .tuner_addr = ADDR_UNSET, |
793 | .radio_addr = ADDR_UNSET, | 793 | .radio_addr = ADDR_UNSET, |
@@ -806,7 +806,7 @@ static const struct cx88_board cx88_boards[] = { | |||
806 | }, | 806 | }, |
807 | [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = { | 807 | [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = { |
808 | .name = "TerraTec Cinergy 1400 DVB-T", | 808 | .name = "TerraTec Cinergy 1400 DVB-T", |
809 | .tuner_type = TUNER_ABSENT, | 809 | .tuner_type = UNSET, |
810 | .input = { { | 810 | .input = { { |
811 | .type = CX88_VMUX_DVB, | 811 | .type = CX88_VMUX_DVB, |
812 | .vmux = 0, | 812 | .vmux = 0, |
@@ -924,7 +924,7 @@ static const struct cx88_board cx88_boards[] = { | |||
924 | }, | 924 | }, |
925 | [CX88_BOARD_WINFAST_DTV1000] = { | 925 | [CX88_BOARD_WINFAST_DTV1000] = { |
926 | .name = "WinFast DTV1000-T", | 926 | .name = "WinFast DTV1000-T", |
927 | .tuner_type = TUNER_ABSENT, | 927 | .tuner_type = UNSET, |
928 | .radio_type = UNSET, | 928 | .radio_type = UNSET, |
929 | .tuner_addr = ADDR_UNSET, | 929 | .tuner_addr = ADDR_UNSET, |
930 | .radio_addr = ADDR_UNSET, | 930 | .radio_addr = ADDR_UNSET, |
@@ -972,7 +972,7 @@ static const struct cx88_board cx88_boards[] = { | |||
972 | }, | 972 | }, |
973 | [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = { | 973 | [CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = { |
974 | .name = "Hauppauge Nova-S-Plus DVB-S", | 974 | .name = "Hauppauge Nova-S-Plus DVB-S", |
975 | .tuner_type = TUNER_ABSENT, | 975 | .tuner_type = UNSET, |
976 | .radio_type = UNSET, | 976 | .radio_type = UNSET, |
977 | .tuner_addr = ADDR_UNSET, | 977 | .tuner_addr = ADDR_UNSET, |
978 | .radio_addr = ADDR_UNSET, | 978 | .radio_addr = ADDR_UNSET, |
@@ -998,7 +998,7 @@ static const struct cx88_board cx88_boards[] = { | |||
998 | }, | 998 | }, |
999 | [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = { | 999 | [CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = { |
1000 | .name = "Hauppauge Nova-SE2 DVB-S", | 1000 | .name = "Hauppauge Nova-SE2 DVB-S", |
1001 | .tuner_type = TUNER_ABSENT, | 1001 | .tuner_type = UNSET, |
1002 | .radio_type = UNSET, | 1002 | .radio_type = UNSET, |
1003 | .tuner_addr = ADDR_UNSET, | 1003 | .tuner_addr = ADDR_UNSET, |
1004 | .radio_addr = ADDR_UNSET, | 1004 | .radio_addr = ADDR_UNSET, |
@@ -1010,7 +1010,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1010 | }, | 1010 | }, |
1011 | [CX88_BOARD_KWORLD_DVBS_100] = { | 1011 | [CX88_BOARD_KWORLD_DVBS_100] = { |
1012 | .name = "KWorld DVB-S 100", | 1012 | .name = "KWorld DVB-S 100", |
1013 | .tuner_type = TUNER_ABSENT, | 1013 | .tuner_type = UNSET, |
1014 | .radio_type = UNSET, | 1014 | .radio_type = UNSET, |
1015 | .tuner_addr = ADDR_UNSET, | 1015 | .tuner_addr = ADDR_UNSET, |
1016 | .radio_addr = ADDR_UNSET, | 1016 | .radio_addr = ADDR_UNSET, |
@@ -1102,7 +1102,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1102 | /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */ | 1102 | /* DTT 7579 Conexant CX22702-19 Conexant CX2388x */ |
1103 | /* Manenti Marco <marco_manenti@colman.it> */ | 1103 | /* Manenti Marco <marco_manenti@colman.it> */ |
1104 | .name = "KWorld/VStream XPert DVB-T with cx22702", | 1104 | .name = "KWorld/VStream XPert DVB-T with cx22702", |
1105 | .tuner_type = TUNER_ABSENT, | 1105 | .tuner_type = UNSET, |
1106 | .radio_type = UNSET, | 1106 | .radio_type = UNSET, |
1107 | .tuner_addr = ADDR_UNSET, | 1107 | .tuner_addr = ADDR_UNSET, |
1108 | .radio_addr = ADDR_UNSET, | 1108 | .radio_addr = ADDR_UNSET, |
@@ -1121,7 +1121,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1121 | }, | 1121 | }, |
1122 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = { | 1122 | [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = { |
1123 | .name = "DViCO FusionHDTV DVB-T Dual Digital", | 1123 | .name = "DViCO FusionHDTV DVB-T Dual Digital", |
1124 | .tuner_type = TUNER_ABSENT, /* No analog tuner */ | 1124 | .tuner_type = UNSET, /* No analog tuner */ |
1125 | .radio_type = UNSET, | 1125 | .radio_type = UNSET, |
1126 | .tuner_addr = ADDR_UNSET, | 1126 | .tuner_addr = ADDR_UNSET, |
1127 | .radio_addr = ADDR_UNSET, | 1127 | .radio_addr = ADDR_UNSET, |
@@ -1356,7 +1356,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1356 | }, | 1356 | }, |
1357 | [CX88_BOARD_GENIATECH_DVBS] = { | 1357 | [CX88_BOARD_GENIATECH_DVBS] = { |
1358 | .name = "Geniatech DVB-S", | 1358 | .name = "Geniatech DVB-S", |
1359 | .tuner_type = TUNER_ABSENT, | 1359 | .tuner_type = UNSET, |
1360 | .radio_type = UNSET, | 1360 | .radio_type = UNSET, |
1361 | .tuner_addr = ADDR_UNSET, | 1361 | .tuner_addr = ADDR_UNSET, |
1362 | .radio_addr = ADDR_UNSET, | 1362 | .radio_addr = ADDR_UNSET, |
@@ -1494,7 +1494,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1494 | }, | 1494 | }, |
1495 | [CX88_BOARD_SAMSUNG_SMT_7020] = { | 1495 | [CX88_BOARD_SAMSUNG_SMT_7020] = { |
1496 | .name = "Samsung SMT 7020 DVB-S", | 1496 | .name = "Samsung SMT 7020 DVB-S", |
1497 | .tuner_type = TUNER_ABSENT, | 1497 | .tuner_type = UNSET, |
1498 | .radio_type = UNSET, | 1498 | .radio_type = UNSET, |
1499 | .tuner_addr = ADDR_UNSET, | 1499 | .tuner_addr = ADDR_UNSET, |
1500 | .radio_addr = ADDR_UNSET, | 1500 | .radio_addr = ADDR_UNSET, |
@@ -1506,7 +1506,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1506 | }, | 1506 | }, |
1507 | [CX88_BOARD_ADSTECH_PTV_390] = { | 1507 | [CX88_BOARD_ADSTECH_PTV_390] = { |
1508 | .name = "ADS Tech Instant Video PCI", | 1508 | .name = "ADS Tech Instant Video PCI", |
1509 | .tuner_type = TUNER_ABSENT, | 1509 | .tuner_type = UNSET, |
1510 | .radio_type = UNSET, | 1510 | .radio_type = UNSET, |
1511 | .tuner_addr = ADDR_UNSET, | 1511 | .tuner_addr = ADDR_UNSET, |
1512 | .radio_addr = ADDR_UNSET, | 1512 | .radio_addr = ADDR_UNSET, |
@@ -1553,7 +1553,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1553 | [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { | 1553 | [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { |
1554 | .name = "DViCO FusionHDTV 5 PCI nano", | 1554 | .name = "DViCO FusionHDTV 5 PCI nano", |
1555 | /* xc3008 tuner, digital only for now */ | 1555 | /* xc3008 tuner, digital only for now */ |
1556 | .tuner_type = TUNER_ABSENT, | 1556 | .tuner_type = UNSET, |
1557 | .radio_type = UNSET, | 1557 | .radio_type = UNSET, |
1558 | .tuner_addr = ADDR_UNSET, | 1558 | .tuner_addr = ADDR_UNSET, |
1559 | .radio_addr = ADDR_UNSET, | 1559 | .radio_addr = ADDR_UNSET, |
@@ -2069,7 +2069,7 @@ static const struct cx88_board cx88_boards[] = { | |||
2069 | }, | 2069 | }, |
2070 | [CX88_BOARD_TBS_8920] = { | 2070 | [CX88_BOARD_TBS_8920] = { |
2071 | .name = "TBS 8920 DVB-S/S2", | 2071 | .name = "TBS 8920 DVB-S/S2", |
2072 | .tuner_type = TUNER_ABSENT, | 2072 | .tuner_type = UNSET, |
2073 | .radio_type = UNSET, | 2073 | .radio_type = UNSET, |
2074 | .tuner_addr = ADDR_UNSET, | 2074 | .tuner_addr = ADDR_UNSET, |
2075 | .radio_addr = ADDR_UNSET, | 2075 | .radio_addr = ADDR_UNSET, |
@@ -2304,7 +2304,7 @@ static const struct cx88_board cx88_boards[] = { | |||
2304 | }, | 2304 | }, |
2305 | [CX88_BOARD_TWINHAN_VP1027_DVBS] = { | 2305 | [CX88_BOARD_TWINHAN_VP1027_DVBS] = { |
2306 | .name = "Twinhan VP-1027 DVB-S", | 2306 | .name = "Twinhan VP-1027 DVB-S", |
2307 | .tuner_type = TUNER_ABSENT, | 2307 | .tuner_type = UNSET, |
2308 | .radio_type = UNSET, | 2308 | .radio_type = UNSET, |
2309 | .tuner_addr = ADDR_UNSET, | 2309 | .tuner_addr = ADDR_UNSET, |
2310 | .radio_addr = ADDR_UNSET, | 2310 | .radio_addr = ADDR_UNSET, |
@@ -2921,33 +2921,33 @@ static const struct { | |||
2921 | int fm; | 2921 | int fm; |
2922 | const char *name; | 2922 | const char *name; |
2923 | } gdi_tuner[] = { | 2923 | } gdi_tuner[] = { |
2924 | [ 0x01 ] = { .id = TUNER_ABSENT, | 2924 | [ 0x01 ] = { .id = UNSET, |
2925 | .name = "NTSC_M" }, | 2925 | .name = "NTSC_M" }, |
2926 | [ 0x02 ] = { .id = TUNER_ABSENT, | 2926 | [ 0x02 ] = { .id = UNSET, |
2927 | .name = "PAL_B" }, | 2927 | .name = "PAL_B" }, |
2928 | [ 0x03 ] = { .id = TUNER_ABSENT, | 2928 | [ 0x03 ] = { .id = UNSET, |
2929 | .name = "PAL_I" }, | 2929 | .name = "PAL_I" }, |
2930 | [ 0x04 ] = { .id = TUNER_ABSENT, | 2930 | [ 0x04 ] = { .id = UNSET, |
2931 | .name = "PAL_D" }, | 2931 | .name = "PAL_D" }, |
2932 | [ 0x05 ] = { .id = TUNER_ABSENT, | 2932 | [ 0x05 ] = { .id = UNSET, |
2933 | .name = "SECAM" }, | 2933 | .name = "SECAM" }, |
2934 | 2934 | ||
2935 | [ 0x10 ] = { .id = TUNER_ABSENT, | 2935 | [ 0x10 ] = { .id = UNSET, |
2936 | .fm = 1, | 2936 | .fm = 1, |
2937 | .name = "TEMIC_4049" }, | 2937 | .name = "TEMIC_4049" }, |
2938 | [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5, | 2938 | [ 0x11 ] = { .id = TUNER_TEMIC_4136FY5, |
2939 | .name = "TEMIC_4136" }, | 2939 | .name = "TEMIC_4136" }, |
2940 | [ 0x12 ] = { .id = TUNER_ABSENT, | 2940 | [ 0x12 ] = { .id = UNSET, |
2941 | .name = "TEMIC_4146" }, | 2941 | .name = "TEMIC_4146" }, |
2942 | 2942 | ||
2943 | [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME, | 2943 | [ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME, |
2944 | .fm = 1, | 2944 | .fm = 1, |
2945 | .name = "PHILIPS_FQ1216_MK3" }, | 2945 | .name = "PHILIPS_FQ1216_MK3" }, |
2946 | [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1, | 2946 | [ 0x21 ] = { .id = UNSET, .fm = 1, |
2947 | .name = "PHILIPS_FQ1236_MK3" }, | 2947 | .name = "PHILIPS_FQ1236_MK3" }, |
2948 | [ 0x22 ] = { .id = TUNER_ABSENT, | 2948 | [ 0x22 ] = { .id = UNSET, |
2949 | .name = "PHILIPS_FI1236_MK3" }, | 2949 | .name = "PHILIPS_FI1236_MK3" }, |
2950 | [ 0x23 ] = { .id = TUNER_ABSENT, | 2950 | [ 0x23 ] = { .id = UNSET, |
2951 | .name = "PHILIPS_FI1216_MK3" }, | 2951 | .name = "PHILIPS_FI1216_MK3" }, |
2952 | }; | 2952 | }; |
2953 | 2953 | ||
@@ -3564,7 +3564,7 @@ static void cx88_card_setup(struct cx88_core *core) | |||
3564 | mode_mask &= ~T_RADIO; | 3564 | mode_mask &= ~T_RADIO; |
3565 | } | 3565 | } |
3566 | 3566 | ||
3567 | if (core->board.tuner_type != TUNER_ABSENT) { | 3567 | if (core->board.tuner_type != UNSET) { |
3568 | tun_setup.mode_mask = mode_mask; | 3568 | tun_setup.mode_mask = mode_mask; |
3569 | tun_setup.type = core->board.tuner_type; | 3569 | tun_setup.type = core->board.tuner_type; |
3570 | tun_setup.addr = core->board.tuner_addr; | 3570 | tun_setup.addr = core->board.tuner_addr; |
@@ -3691,6 +3691,11 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) | |||
3691 | core->nr = nr; | 3691 | core->nr = nr; |
3692 | sprintf(core->name, "cx88[%d]", core->nr); | 3692 | sprintf(core->name, "cx88[%d]", core->nr); |
3693 | 3693 | ||
3694 | core->tvnorm = V4L2_STD_NTSC_M; | ||
3695 | core->width = 320; | ||
3696 | core->height = 240; | ||
3697 | core->field = V4L2_FIELD_INTERLACED; | ||
3698 | |||
3694 | strcpy(core->v4l2_dev.name, core->name); | 3699 | strcpy(core->v4l2_dev.name, core->name); |
3695 | if (v4l2_device_register(NULL, &core->v4l2_dev)) { | 3700 | if (v4l2_device_register(NULL, &core->v4l2_dev)) { |
3696 | kfree(core); | 3701 | kfree(core); |
@@ -3772,7 +3777,7 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr) | |||
3772 | cx88_i2c_init(core, pci); | 3777 | cx88_i2c_init(core, pci); |
3773 | 3778 | ||
3774 | /* load tuner module, if needed */ | 3779 | /* load tuner module, if needed */ |
3775 | if (TUNER_ABSENT != core->board.tuner_type) { | 3780 | if (UNSET != core->board.tuner_type) { |
3776 | /* Ignore 0x6b and 0x6f on cx88 boards. | 3781 | /* Ignore 0x6b and 0x6f on cx88 boards. |
3777 | * FusionHDTV5 RT Gold has an ir receiver at 0x6b | 3782 | * FusionHDTV5 RT Gold has an ir receiver at 0x6b |
3778 | * and an RTC at 0x6f which can get corrupted if probed. */ | 3783 | * and an RTC at 0x6f which can get corrupted if probed. */ |
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c index 71630238027b..dee177ed5fe9 100644 --- a/drivers/media/pci/cx88/cx88-core.c +++ b/drivers/media/pci/cx88/cx88-core.c | |||
@@ -76,11 +76,16 @@ static DEFINE_MUTEX(devlist); | |||
76 | static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, | 76 | static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, |
77 | unsigned int offset, u32 sync_line, | 77 | unsigned int offset, u32 sync_line, |
78 | unsigned int bpl, unsigned int padding, | 78 | unsigned int bpl, unsigned int padding, |
79 | unsigned int lines, unsigned int lpi) | 79 | unsigned int lines, unsigned int lpi, bool jump) |
80 | { | 80 | { |
81 | struct scatterlist *sg; | 81 | struct scatterlist *sg; |
82 | unsigned int line,todo,sol; | 82 | unsigned int line,todo,sol; |
83 | 83 | ||
84 | if (jump) { | ||
85 | (*rp++) = cpu_to_le32(RISC_JUMP); | ||
86 | (*rp++) = 0; | ||
87 | } | ||
88 | |||
84 | /* sync instruction */ | 89 | /* sync instruction */ |
85 | if (sync_line != NO_SYNC_LINE) | 90 | if (sync_line != NO_SYNC_LINE) |
86 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | 91 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); |
@@ -90,7 +95,7 @@ static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, | |||
90 | for (line = 0; line < lines; line++) { | 95 | for (line = 0; line < lines; line++) { |
91 | while (offset && offset >= sg_dma_len(sg)) { | 96 | while (offset && offset >= sg_dma_len(sg)) { |
92 | offset -= sg_dma_len(sg); | 97 | offset -= sg_dma_len(sg); |
93 | sg++; | 98 | sg = sg_next(sg); |
94 | } | 99 | } |
95 | if (lpi && line>0 && !(line % lpi)) | 100 | if (lpi && line>0 && !(line % lpi)) |
96 | sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; | 101 | sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC; |
@@ -109,13 +114,13 @@ static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, | |||
109 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); | 114 | *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); |
110 | todo -= (sg_dma_len(sg)-offset); | 115 | todo -= (sg_dma_len(sg)-offset); |
111 | offset = 0; | 116 | offset = 0; |
112 | sg++; | 117 | sg = sg_next(sg); |
113 | while (todo > sg_dma_len(sg)) { | 118 | while (todo > sg_dma_len(sg)) { |
114 | *(rp++)=cpu_to_le32(RISC_WRITE| | 119 | *(rp++)=cpu_to_le32(RISC_WRITE| |
115 | sg_dma_len(sg)); | 120 | sg_dma_len(sg)); |
116 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); | 121 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); |
117 | todo -= sg_dma_len(sg); | 122 | todo -= sg_dma_len(sg); |
118 | sg++; | 123 | sg = sg_next(sg); |
119 | } | 124 | } |
120 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); | 125 | *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); |
121 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); | 126 | *(rp++)=cpu_to_le32(sg_dma_address(sg)); |
@@ -127,14 +132,13 @@ static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist, | |||
127 | return rp; | 132 | return rp; |
128 | } | 133 | } |
129 | 134 | ||
130 | int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 135 | int cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc, |
131 | struct scatterlist *sglist, | 136 | struct scatterlist *sglist, |
132 | unsigned int top_offset, unsigned int bottom_offset, | 137 | unsigned int top_offset, unsigned int bottom_offset, |
133 | unsigned int bpl, unsigned int padding, unsigned int lines) | 138 | unsigned int bpl, unsigned int padding, unsigned int lines) |
134 | { | 139 | { |
135 | u32 instructions,fields; | 140 | u32 instructions,fields; |
136 | __le32 *rp; | 141 | __le32 *rp; |
137 | int rc; | ||
138 | 142 | ||
139 | fields = 0; | 143 | fields = 0; |
140 | if (UNSET != top_offset) | 144 | if (UNSET != top_offset) |
@@ -147,18 +151,21 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
147 | can cause next bpl to start close to a page border. First DMA | 151 | can cause next bpl to start close to a page border. First DMA |
148 | region may be smaller than PAGE_SIZE */ | 152 | region may be smaller than PAGE_SIZE */ |
149 | instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); | 153 | instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); |
150 | instructions += 2; | 154 | instructions += 4; |
151 | if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) | 155 | risc->size = instructions * 8; |
152 | return rc; | 156 | risc->dma = 0; |
157 | risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma); | ||
158 | if (NULL == risc->cpu) | ||
159 | return -ENOMEM; | ||
153 | 160 | ||
154 | /* write risc instructions */ | 161 | /* write risc instructions */ |
155 | rp = risc->cpu; | 162 | rp = risc->cpu; |
156 | if (UNSET != top_offset) | 163 | if (UNSET != top_offset) |
157 | rp = cx88_risc_field(rp, sglist, top_offset, 0, | 164 | rp = cx88_risc_field(rp, sglist, top_offset, 0, |
158 | bpl, padding, lines, 0); | 165 | bpl, padding, lines, 0, true); |
159 | if (UNSET != bottom_offset) | 166 | if (UNSET != bottom_offset) |
160 | rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, | 167 | rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200, |
161 | bpl, padding, lines, 0); | 168 | bpl, padding, lines, 0, top_offset == UNSET); |
162 | 169 | ||
163 | /* save pointer to jmp instruction address */ | 170 | /* save pointer to jmp instruction address */ |
164 | risc->jmp = rp; | 171 | risc->jmp = rp; |
@@ -166,26 +173,28 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
166 | return 0; | 173 | return 0; |
167 | } | 174 | } |
168 | 175 | ||
169 | int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 176 | int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc, |
170 | struct scatterlist *sglist, unsigned int bpl, | 177 | struct scatterlist *sglist, unsigned int bpl, |
171 | unsigned int lines, unsigned int lpi) | 178 | unsigned int lines, unsigned int lpi) |
172 | { | 179 | { |
173 | u32 instructions; | 180 | u32 instructions; |
174 | __le32 *rp; | 181 | __le32 *rp; |
175 | int rc; | ||
176 | 182 | ||
177 | /* estimate risc mem: worst case is one write per page border + | 183 | /* estimate risc mem: worst case is one write per page border + |
178 | one write per scan line + syncs + jump (all 2 dwords). Here | 184 | one write per scan line + syncs + jump (all 2 dwords). Here |
179 | there is no padding and no sync. First DMA region may be smaller | 185 | there is no padding and no sync. First DMA region may be smaller |
180 | than PAGE_SIZE */ | 186 | than PAGE_SIZE */ |
181 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; | 187 | instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; |
182 | instructions += 1; | 188 | instructions += 3; |
183 | if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) | 189 | risc->size = instructions * 8; |
184 | return rc; | 190 | risc->dma = 0; |
191 | risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma); | ||
192 | if (NULL == risc->cpu) | ||
193 | return -ENOMEM; | ||
185 | 194 | ||
186 | /* write risc instructions */ | 195 | /* write risc instructions */ |
187 | rp = risc->cpu; | 196 | rp = risc->cpu; |
188 | rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi); | 197 | rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi, !lpi); |
189 | 198 | ||
190 | /* save pointer to jmp instruction address */ | 199 | /* save pointer to jmp instruction address */ |
191 | risc->jmp = rp; | 200 | risc->jmp = rp; |
@@ -193,39 +202,6 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
193 | return 0; | 202 | return 0; |
194 | } | 203 | } |
195 | 204 | ||
196 | int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
197 | u32 reg, u32 mask, u32 value) | ||
198 | { | ||
199 | __le32 *rp; | ||
200 | int rc; | ||
201 | |||
202 | if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0) | ||
203 | return rc; | ||
204 | |||
205 | /* write risc instructions */ | ||
206 | rp = risc->cpu; | ||
207 | *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM); | ||
208 | *(rp++) = cpu_to_le32(reg); | ||
209 | *(rp++) = cpu_to_le32(value); | ||
210 | *(rp++) = cpu_to_le32(mask); | ||
211 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
212 | *(rp++) = cpu_to_le32(risc->dma); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | void | ||
217 | cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) | ||
218 | { | ||
219 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | ||
220 | |||
221 | BUG_ON(in_interrupt()); | ||
222 | videobuf_waiton(q, &buf->vb, 0, 0); | ||
223 | videobuf_dma_unmap(q->dev, dma); | ||
224 | videobuf_dma_free(dma); | ||
225 | btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); | ||
226 | buf->vb.state = VIDEOBUF_NEEDS_INIT; | ||
227 | } | ||
228 | |||
229 | /* ------------------------------------------------------------------ */ | 205 | /* ------------------------------------------------------------------ */ |
230 | /* our SRAM memory layout */ | 206 | /* our SRAM memory layout */ |
231 | 207 | ||
@@ -539,33 +515,12 @@ void cx88_wakeup(struct cx88_core *core, | |||
539 | struct cx88_dmaqueue *q, u32 count) | 515 | struct cx88_dmaqueue *q, u32 count) |
540 | { | 516 | { |
541 | struct cx88_buffer *buf; | 517 | struct cx88_buffer *buf; |
542 | int bc; | 518 | |
543 | 519 | buf = list_entry(q->active.next, | |
544 | for (bc = 0;; bc++) { | 520 | struct cx88_buffer, list); |
545 | if (list_empty(&q->active)) | 521 | v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); |
546 | break; | 522 | list_del(&buf->list); |
547 | buf = list_entry(q->active.next, | 523 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); |
548 | struct cx88_buffer, vb.queue); | ||
549 | /* count comes from the hw and is is 16bit wide -- | ||
550 | * this trick handles wrap-arounds correctly for | ||
551 | * up to 32767 buffers in flight... */ | ||
552 | if ((s16) (count - buf->count) < 0) | ||
553 | break; | ||
554 | v4l2_get_timestamp(&buf->vb.ts); | ||
555 | dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i, | ||
556 | count, buf->count); | ||
557 | buf->vb.state = VIDEOBUF_DONE; | ||
558 | list_del(&buf->vb.queue); | ||
559 | wake_up(&buf->vb.done); | ||
560 | } | ||
561 | if (list_empty(&q->active)) { | ||
562 | del_timer(&q->timeout); | ||
563 | } else { | ||
564 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
565 | } | ||
566 | if (bc != 1) | ||
567 | dprintk(2, "%s: %d buffers handled (should be 1)\n", | ||
568 | __func__, bc); | ||
569 | } | 524 | } |
570 | 525 | ||
571 | void cx88_shutdown(struct cx88_core *core) | 526 | void cx88_shutdown(struct cx88_core *core) |
@@ -909,6 +864,13 @@ int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm) | |||
909 | u32 bdelay,agcdelay,htotal; | 864 | u32 bdelay,agcdelay,htotal; |
910 | u32 cxiformat, cxoformat; | 865 | u32 cxiformat, cxoformat; |
911 | 866 | ||
867 | if (norm == core->tvnorm) | ||
868 | return 0; | ||
869 | if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) || | ||
870 | vb2_is_busy(&core->v4ldev->vb2_vbiq))) | ||
871 | return -EBUSY; | ||
872 | if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq)) | ||
873 | return -EBUSY; | ||
912 | core->tvnorm = norm; | 874 | core->tvnorm = norm; |
913 | fsc8 = norm_fsc8(norm); | 875 | fsc8 = norm_fsc8(norm); |
914 | adc_clock = xtal; | 876 | adc_clock = xtal; |
@@ -1043,6 +1005,7 @@ struct video_device *cx88_vdev_init(struct cx88_core *core, | |||
1043 | vfd->v4l2_dev = &core->v4l2_dev; | 1005 | vfd->v4l2_dev = &core->v4l2_dev; |
1044 | vfd->dev_parent = &pci->dev; | 1006 | vfd->dev_parent = &pci->dev; |
1045 | vfd->release = video_device_release; | 1007 | vfd->release = video_device_release; |
1008 | vfd->lock = &core->lock; | ||
1046 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 1009 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", |
1047 | core->name, type, core->board.name); | 1010 | core->name, type, core->board.name); |
1048 | return vfd; | 1011 | return vfd; |
@@ -1114,8 +1077,6 @@ EXPORT_SYMBOL(cx88_shutdown); | |||
1114 | 1077 | ||
1115 | EXPORT_SYMBOL(cx88_risc_buffer); | 1078 | EXPORT_SYMBOL(cx88_risc_buffer); |
1116 | EXPORT_SYMBOL(cx88_risc_databuffer); | 1079 | EXPORT_SYMBOL(cx88_risc_databuffer); |
1117 | EXPORT_SYMBOL(cx88_risc_stopper); | ||
1118 | EXPORT_SYMBOL(cx88_free_buffer); | ||
1119 | 1080 | ||
1120 | EXPORT_SYMBOL(cx88_sram_channels); | 1081 | EXPORT_SYMBOL(cx88_sram_channels); |
1121 | EXPORT_SYMBOL(cx88_sram_channel_setup); | 1082 | EXPORT_SYMBOL(cx88_sram_channel_setup); |
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c index 053ed1ba1d85..c344bfd0b896 100644 --- a/drivers/media/pci/cx88/cx88-dvb.c +++ b/drivers/media/pci/cx88/cx88-dvb.c | |||
@@ -82,43 +82,89 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | |||
82 | 82 | ||
83 | /* ------------------------------------------------------------------ */ | 83 | /* ------------------------------------------------------------------ */ |
84 | 84 | ||
85 | static int dvb_buf_setup(struct videobuf_queue *q, | 85 | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
86 | unsigned int *count, unsigned int *size) | 86 | unsigned int *num_buffers, unsigned int *num_planes, |
87 | unsigned int sizes[], void *alloc_ctxs[]) | ||
87 | { | 88 | { |
88 | struct cx8802_dev *dev = q->priv_data; | 89 | struct cx8802_dev *dev = q->drv_priv; |
89 | 90 | ||
91 | *num_planes = 1; | ||
90 | dev->ts_packet_size = 188 * 4; | 92 | dev->ts_packet_size = 188 * 4; |
91 | dev->ts_packet_count = dvb_buf_tscnt; | 93 | dev->ts_packet_count = dvb_buf_tscnt; |
92 | 94 | sizes[0] = dev->ts_packet_size * dev->ts_packet_count; | |
93 | *size = dev->ts_packet_size * dev->ts_packet_count; | 95 | *num_buffers = dvb_buf_tscnt; |
94 | *count = dvb_buf_tscnt; | ||
95 | return 0; | 96 | return 0; |
96 | } | 97 | } |
97 | 98 | ||
98 | static int dvb_buf_prepare(struct videobuf_queue *q, | 99 | static int buffer_prepare(struct vb2_buffer *vb) |
99 | struct videobuf_buffer *vb, enum v4l2_field field) | 100 | { |
101 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; | ||
102 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
103 | |||
104 | return cx8802_buf_prepare(vb->vb2_queue, dev, buf); | ||
105 | } | ||
106 | |||
107 | static void buffer_finish(struct vb2_buffer *vb) | ||
108 | { | ||
109 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; | ||
110 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
111 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||
112 | struct cx88_riscmem *risc = &buf->risc; | ||
113 | |||
114 | if (risc->cpu) | ||
115 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); | ||
116 | memset(risc, 0, sizeof(*risc)); | ||
117 | |||
118 | dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); | ||
119 | } | ||
120 | |||
121 | static void buffer_queue(struct vb2_buffer *vb) | ||
100 | { | 122 | { |
101 | struct cx8802_dev *dev = q->priv_data; | 123 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
102 | return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); | 124 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
125 | |||
126 | cx8802_buf_queue(dev, buf); | ||
103 | } | 127 | } |
104 | 128 | ||
105 | static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | 129 | static int start_streaming(struct vb2_queue *q, unsigned int count) |
106 | { | 130 | { |
107 | struct cx8802_dev *dev = q->priv_data; | 131 | struct cx8802_dev *dev = q->drv_priv; |
108 | cx8802_buf_queue(dev, (struct cx88_buffer*)vb); | 132 | struct cx88_dmaqueue *dmaq = &dev->mpegq; |
133 | struct cx88_buffer *buf; | ||
134 | |||
135 | buf = list_entry(dmaq->active.next, struct cx88_buffer, list); | ||
136 | cx8802_start_dma(dev, dmaq, buf); | ||
137 | return 0; | ||
109 | } | 138 | } |
110 | 139 | ||
111 | static void dvb_buf_release(struct videobuf_queue *q, | 140 | static void stop_streaming(struct vb2_queue *q) |
112 | struct videobuf_buffer *vb) | ||
113 | { | 141 | { |
114 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | 142 | struct cx8802_dev *dev = q->drv_priv; |
143 | struct cx88_dmaqueue *dmaq = &dev->mpegq; | ||
144 | unsigned long flags; | ||
145 | |||
146 | cx8802_cancel_buffers(dev); | ||
147 | |||
148 | spin_lock_irqsave(&dev->slock, flags); | ||
149 | while (!list_empty(&dmaq->active)) { | ||
150 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
151 | struct cx88_buffer, list); | ||
152 | |||
153 | list_del(&buf->list); | ||
154 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
155 | } | ||
156 | spin_unlock_irqrestore(&dev->slock, flags); | ||
115 | } | 157 | } |
116 | 158 | ||
117 | static const struct videobuf_queue_ops dvb_qops = { | 159 | static struct vb2_ops dvb_qops = { |
118 | .buf_setup = dvb_buf_setup, | 160 | .queue_setup = queue_setup, |
119 | .buf_prepare = dvb_buf_prepare, | 161 | .buf_prepare = buffer_prepare, |
120 | .buf_queue = dvb_buf_queue, | 162 | .buf_finish = buffer_finish, |
121 | .buf_release = dvb_buf_release, | 163 | .buf_queue = buffer_queue, |
164 | .wait_prepare = vb2_ops_wait_prepare, | ||
165 | .wait_finish = vb2_ops_wait_finish, | ||
166 | .start_streaming = start_streaming, | ||
167 | .stop_streaming = stop_streaming, | ||
122 | }; | 168 | }; |
123 | 169 | ||
124 | /* ------------------------------------------------------------------ */ | 170 | /* ------------------------------------------------------------------ */ |
@@ -130,7 +176,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | |||
130 | int ret = 0; | 176 | int ret = 0; |
131 | int fe_id; | 177 | int fe_id; |
132 | 178 | ||
133 | fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe); | 179 | fe_id = vb2_dvb_find_frontend(&dev->frontends, fe); |
134 | if (!fe_id) { | 180 | if (!fe_id) { |
135 | printk(KERN_ERR "%s() No frontend found\n", __func__); | 181 | printk(KERN_ERR "%s() No frontend found\n", __func__); |
136 | return -EINVAL; | 182 | return -EINVAL; |
@@ -154,8 +200,8 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) | |||
154 | 200 | ||
155 | static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) | 201 | static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) |
156 | { | 202 | { |
157 | struct videobuf_dvb_frontends *f; | 203 | struct vb2_dvb_frontends *f; |
158 | struct videobuf_dvb_frontend *fe; | 204 | struct vb2_dvb_frontend *fe; |
159 | 205 | ||
160 | if (!core->dvbdev) | 206 | if (!core->dvbdev) |
161 | return; | 207 | return; |
@@ -166,9 +212,9 @@ static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open) | |||
166 | return; | 212 | return; |
167 | 213 | ||
168 | if (f->gate <= 1) /* undefined or fe0 */ | 214 | if (f->gate <= 1) /* undefined or fe0 */ |
169 | fe = videobuf_dvb_get_frontend(f, 1); | 215 | fe = vb2_dvb_get_frontend(f, 1); |
170 | else | 216 | else |
171 | fe = videobuf_dvb_get_frontend(f, f->gate); | 217 | fe = vb2_dvb_get_frontend(f, f->gate); |
172 | 218 | ||
173 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) | 219 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) |
174 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); | 220 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); |
@@ -565,7 +611,7 @@ static const struct xc5000_config dvico_fusionhdtv7_tuner_config = { | |||
565 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | 611 | static int attach_xc3028(u8 addr, struct cx8802_dev *dev) |
566 | { | 612 | { |
567 | struct dvb_frontend *fe; | 613 | struct dvb_frontend *fe; |
568 | struct videobuf_dvb_frontend *fe0 = NULL; | 614 | struct vb2_dvb_frontend *fe0 = NULL; |
569 | struct xc2028_ctrl ctl; | 615 | struct xc2028_ctrl ctl; |
570 | struct xc2028_config cfg = { | 616 | struct xc2028_config cfg = { |
571 | .i2c_adap = &dev->core->i2c_adap, | 617 | .i2c_adap = &dev->core->i2c_adap, |
@@ -574,7 +620,7 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
574 | }; | 620 | }; |
575 | 621 | ||
576 | /* Get the first frontend */ | 622 | /* Get the first frontend */ |
577 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | 623 | fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); |
578 | if (!fe0) | 624 | if (!fe0) |
579 | return -EINVAL; | 625 | return -EINVAL; |
580 | 626 | ||
@@ -611,10 +657,10 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) | |||
611 | static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg) | 657 | static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg) |
612 | { | 658 | { |
613 | struct dvb_frontend *fe; | 659 | struct dvb_frontend *fe; |
614 | struct videobuf_dvb_frontend *fe0 = NULL; | 660 | struct vb2_dvb_frontend *fe0 = NULL; |
615 | 661 | ||
616 | /* Get the first frontend */ | 662 | /* Get the first frontend */ |
617 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | 663 | fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); |
618 | if (!fe0) | 664 | if (!fe0) |
619 | return -EINVAL; | 665 | return -EINVAL; |
620 | 666 | ||
@@ -745,7 +791,7 @@ static const struct stv0288_config tevii_tuner_earda_config = { | |||
745 | static int cx8802_alloc_frontends(struct cx8802_dev *dev) | 791 | static int cx8802_alloc_frontends(struct cx8802_dev *dev) |
746 | { | 792 | { |
747 | struct cx88_core *core = dev->core; | 793 | struct cx88_core *core = dev->core; |
748 | struct videobuf_dvb_frontend *fe = NULL; | 794 | struct vb2_dvb_frontend *fe = NULL; |
749 | int i; | 795 | int i; |
750 | 796 | ||
751 | mutex_init(&dev->frontends.lock); | 797 | mutex_init(&dev->frontends.lock); |
@@ -757,10 +803,10 @@ static int cx8802_alloc_frontends(struct cx8802_dev *dev) | |||
757 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, | 803 | printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, |
758 | core->board.num_frontends); | 804 | core->board.num_frontends); |
759 | for (i = 1; i <= core->board.num_frontends; i++) { | 805 | for (i = 1; i <= core->board.num_frontends; i++) { |
760 | fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); | 806 | fe = vb2_dvb_alloc_frontend(&dev->frontends, i); |
761 | if (!fe) { | 807 | if (!fe) { |
762 | printk(KERN_ERR "%s() failed to alloc\n", __func__); | 808 | printk(KERN_ERR "%s() failed to alloc\n", __func__); |
763 | videobuf_dvb_dealloc_frontends(&dev->frontends); | 809 | vb2_dvb_dealloc_frontends(&dev->frontends); |
764 | return -ENOMEM; | 810 | return -ENOMEM; |
765 | } | 811 | } |
766 | } | 812 | } |
@@ -958,7 +1004,7 @@ static const struct stv0299_config samsung_stv0299_config = { | |||
958 | static int dvb_register(struct cx8802_dev *dev) | 1004 | static int dvb_register(struct cx8802_dev *dev) |
959 | { | 1005 | { |
960 | struct cx88_core *core = dev->core; | 1006 | struct cx88_core *core = dev->core; |
961 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; | 1007 | struct vb2_dvb_frontend *fe0, *fe1 = NULL; |
962 | int mfe_shared = 0; /* bus not shared by default */ | 1008 | int mfe_shared = 0; /* bus not shared by default */ |
963 | int res = -EINVAL; | 1009 | int res = -EINVAL; |
964 | 1010 | ||
@@ -968,7 +1014,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
968 | } | 1014 | } |
969 | 1015 | ||
970 | /* Get the first frontend */ | 1016 | /* Get the first frontend */ |
971 | fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); | 1017 | fe0 = vb2_dvb_get_frontend(&dev->frontends, 1); |
972 | if (!fe0) | 1018 | if (!fe0) |
973 | goto frontend_detach; | 1019 | goto frontend_detach; |
974 | 1020 | ||
@@ -1046,7 +1092,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1046 | goto frontend_detach; | 1092 | goto frontend_detach; |
1047 | } | 1093 | } |
1048 | /* MFE frontend 2 */ | 1094 | /* MFE frontend 2 */ |
1049 | fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); | 1095 | fe1 = vb2_dvb_get_frontend(&dev->frontends, 2); |
1050 | if (!fe1) | 1096 | if (!fe1) |
1051 | goto frontend_detach; | 1097 | goto frontend_detach; |
1052 | /* DVB-T init */ | 1098 | /* DVB-T init */ |
@@ -1415,7 +1461,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1415 | goto frontend_detach; | 1461 | goto frontend_detach; |
1416 | } | 1462 | } |
1417 | /* MFE frontend 2 */ | 1463 | /* MFE frontend 2 */ |
1418 | fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2); | 1464 | fe1 = vb2_dvb_get_frontend(&dev->frontends, 2); |
1419 | if (!fe1) | 1465 | if (!fe1) |
1420 | goto frontend_detach; | 1466 | goto frontend_detach; |
1421 | /* DVB-T Init */ | 1467 | /* DVB-T Init */ |
@@ -1594,7 +1640,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1594 | call_all(core, core, s_power, 0); | 1640 | call_all(core, core, s_power, 0); |
1595 | 1641 | ||
1596 | /* register everything */ | 1642 | /* register everything */ |
1597 | res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | 1643 | res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, |
1598 | &dev->pci->dev, adapter_nr, mfe_shared); | 1644 | &dev->pci->dev, adapter_nr, mfe_shared); |
1599 | if (res) | 1645 | if (res) |
1600 | goto frontend_detach; | 1646 | goto frontend_detach; |
@@ -1602,7 +1648,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1602 | 1648 | ||
1603 | frontend_detach: | 1649 | frontend_detach: |
1604 | core->gate_ctrl = NULL; | 1650 | core->gate_ctrl = NULL; |
1605 | videobuf_dvb_dealloc_frontends(&dev->frontends); | 1651 | vb2_dvb_dealloc_frontends(&dev->frontends); |
1606 | return res; | 1652 | return res; |
1607 | } | 1653 | } |
1608 | 1654 | ||
@@ -1697,7 +1743,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
1697 | struct cx88_core *core = drv->core; | 1743 | struct cx88_core *core = drv->core; |
1698 | struct cx8802_dev *dev = drv->core->dvbdev; | 1744 | struct cx8802_dev *dev = drv->core->dvbdev; |
1699 | int err; | 1745 | int err; |
1700 | struct videobuf_dvb_frontend *fe; | 1746 | struct vb2_dvb_frontend *fe; |
1701 | int i; | 1747 | int i; |
1702 | 1748 | ||
1703 | dprintk( 1, "%s\n", __func__); | 1749 | dprintk( 1, "%s\n", __func__); |
@@ -1726,19 +1772,31 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
1726 | 1772 | ||
1727 | err = -ENODEV; | 1773 | err = -ENODEV; |
1728 | for (i = 1; i <= core->board.num_frontends; i++) { | 1774 | for (i = 1; i <= core->board.num_frontends; i++) { |
1729 | fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i); | 1775 | struct vb2_queue *q; |
1776 | |||
1777 | fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i); | ||
1730 | if (fe == NULL) { | 1778 | if (fe == NULL) { |
1731 | printk(KERN_ERR "%s() failed to get frontend(%d)\n", | 1779 | printk(KERN_ERR "%s() failed to get frontend(%d)\n", |
1732 | __func__, i); | 1780 | __func__, i); |
1733 | goto fail_probe; | 1781 | goto fail_probe; |
1734 | } | 1782 | } |
1735 | videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops, | 1783 | q = &fe->dvb.dvbq; |
1736 | &dev->pci->dev, &dev->slock, | 1784 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
1737 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 1785 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; |
1738 | V4L2_FIELD_TOP, | 1786 | q->gfp_flags = GFP_DMA32; |
1739 | sizeof(struct cx88_buffer), | 1787 | q->min_buffers_needed = 2; |
1740 | dev, NULL); | 1788 | q->drv_priv = dev; |
1741 | /* init struct videobuf_dvb */ | 1789 | q->buf_struct_size = sizeof(struct cx88_buffer); |
1790 | q->ops = &dvb_qops; | ||
1791 | q->mem_ops = &vb2_dma_sg_memops; | ||
1792 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1793 | q->lock = &core->lock; | ||
1794 | |||
1795 | err = vb2_queue_init(q); | ||
1796 | if (err < 0) | ||
1797 | goto fail_probe; | ||
1798 | |||
1799 | /* init struct vb2_dvb */ | ||
1742 | fe->dvb.name = dev->core->name; | 1800 | fe->dvb.name = dev->core->name; |
1743 | } | 1801 | } |
1744 | 1802 | ||
@@ -1749,7 +1807,7 @@ static int cx8802_dvb_probe(struct cx8802_driver *drv) | |||
1749 | core->name, err); | 1807 | core->name, err); |
1750 | return err; | 1808 | return err; |
1751 | fail_probe: | 1809 | fail_probe: |
1752 | videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends); | 1810 | vb2_dvb_dealloc_frontends(&core->dvbdev->frontends); |
1753 | fail_core: | 1811 | fail_core: |
1754 | return err; | 1812 | return err; |
1755 | } | 1813 | } |
@@ -1761,7 +1819,7 @@ static int cx8802_dvb_remove(struct cx8802_driver *drv) | |||
1761 | 1819 | ||
1762 | dprintk( 1, "%s\n", __func__); | 1820 | dprintk( 1, "%s\n", __func__); |
1763 | 1821 | ||
1764 | videobuf_dvb_unregister_bus(&dev->frontends); | 1822 | vb2_dvb_unregister_bus(&dev->frontends); |
1765 | 1823 | ||
1766 | vp3054_i2c_remove(dev); | 1824 | vp3054_i2c_remove(dev); |
1767 | 1825 | ||
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c index 74b7b8614c23..f181a3a10389 100644 --- a/drivers/media/pci/cx88/cx88-mpeg.c +++ b/drivers/media/pci/cx88/cx88-mpeg.c | |||
@@ -86,21 +86,21 @@ static LIST_HEAD(cx8802_devlist); | |||
86 | static DEFINE_MUTEX(cx8802_mutex); | 86 | static DEFINE_MUTEX(cx8802_mutex); |
87 | /* ------------------------------------------------------------------ */ | 87 | /* ------------------------------------------------------------------ */ |
88 | 88 | ||
89 | static int cx8802_start_dma(struct cx8802_dev *dev, | 89 | int cx8802_start_dma(struct cx8802_dev *dev, |
90 | struct cx88_dmaqueue *q, | 90 | struct cx88_dmaqueue *q, |
91 | struct cx88_buffer *buf) | 91 | struct cx88_buffer *buf) |
92 | { | 92 | { |
93 | struct cx88_core *core = dev->core; | 93 | struct cx88_core *core = dev->core; |
94 | 94 | ||
95 | dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", | 95 | dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", |
96 | buf->vb.width, buf->vb.height, buf->vb.field); | 96 | core->width, core->height, core->field); |
97 | 97 | ||
98 | /* setup fifo + format */ | 98 | /* setup fifo + format */ |
99 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], | 99 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], |
100 | dev->ts_packet_size, buf->risc.dma); | 100 | dev->ts_packet_size, buf->risc.dma); |
101 | 101 | ||
102 | /* write TS length to chip */ | 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 | 104 | ||
105 | /* FIXME: this needs a review. | 105 | /* FIXME: this needs a review. |
106 | * also: move to cx88-blackbird + cx88-dvb source files? */ | 106 | * also: move to cx88-blackbird + cx88-dvb source files? */ |
@@ -210,83 +210,44 @@ static int cx8802_restart_queue(struct cx8802_dev *dev, | |||
210 | 210 | ||
211 | dprintk( 1, "cx8802_restart_queue\n" ); | 211 | dprintk( 1, "cx8802_restart_queue\n" ); |
212 | if (list_empty(&q->active)) | 212 | if (list_empty(&q->active)) |
213 | { | ||
214 | struct cx88_buffer *prev; | ||
215 | prev = NULL; | ||
216 | |||
217 | dprintk(1, "cx8802_restart_queue: queue is empty\n" ); | ||
218 | |||
219 | for (;;) { | ||
220 | if (list_empty(&q->queued)) | ||
221 | return 0; | ||
222 | buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); | ||
223 | if (NULL == prev) { | ||
224 | list_move_tail(&buf->vb.queue, &q->active); | ||
225 | cx8802_start_dma(dev, q, buf); | ||
226 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
227 | buf->count = q->count++; | ||
228 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
229 | dprintk(1,"[%p/%d] restart_queue - first active\n", | ||
230 | buf,buf->vb.i); | ||
231 | |||
232 | } else if (prev->vb.width == buf->vb.width && | ||
233 | prev->vb.height == buf->vb.height && | ||
234 | prev->fmt == buf->fmt) { | ||
235 | list_move_tail(&buf->vb.queue, &q->active); | ||
236 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
237 | buf->count = q->count++; | ||
238 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
239 | dprintk(1,"[%p/%d] restart_queue - move to active\n", | ||
240 | buf,buf->vb.i); | ||
241 | } else { | ||
242 | return 0; | ||
243 | } | ||
244 | prev = buf; | ||
245 | } | ||
246 | return 0; | 213 | return 0; |
247 | } | ||
248 | 214 | ||
249 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 215 | buf = list_entry(q->active.next, struct cx88_buffer, list); |
250 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 216 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
251 | buf, buf->vb.i); | 217 | buf, buf->vb.v4l2_buf.index); |
252 | cx8802_start_dma(dev, q, buf); | 218 | cx8802_start_dma(dev, q, buf); |
253 | list_for_each_entry(buf, &q->active, vb.queue) | 219 | list_for_each_entry(buf, &q->active, list) |
254 | buf->count = q->count++; | 220 | buf->count = q->count++; |
255 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
256 | return 0; | 221 | return 0; |
257 | } | 222 | } |
258 | 223 | ||
259 | /* ------------------------------------------------------------------ */ | 224 | /* ------------------------------------------------------------------ */ |
260 | 225 | ||
261 | int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev, | 226 | int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev, |
262 | struct cx88_buffer *buf, enum v4l2_field field) | 227 | struct cx88_buffer *buf) |
263 | { | 228 | { |
264 | int size = dev->ts_packet_size * dev->ts_packet_count; | 229 | int size = dev->ts_packet_size * dev->ts_packet_count; |
265 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | 230 | struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0); |
231 | struct cx88_riscmem *risc = &buf->risc; | ||
266 | int rc; | 232 | int rc; |
267 | 233 | ||
268 | dprintk(1, "%s: %p\n", __func__, buf); | 234 | if (vb2_plane_size(&buf->vb, 0) < size) |
269 | if (0 != buf->vb.baddr && buf->vb.bsize < size) | ||
270 | return -EINVAL; | 235 | return -EINVAL; |
236 | vb2_set_plane_payload(&buf->vb, 0, size); | ||
271 | 237 | ||
272 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 238 | rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); |
273 | buf->vb.width = dev->ts_packet_size; | 239 | if (!rc) |
274 | buf->vb.height = dev->ts_packet_count; | 240 | return -EIO; |
275 | buf->vb.size = size; | 241 | |
276 | buf->vb.field = field /*V4L2_FIELD_TOP*/; | 242 | rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl, |
277 | 243 | dev->ts_packet_size, dev->ts_packet_count, 0); | |
278 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) | 244 | if (rc) { |
279 | goto fail; | 245 | if (risc->cpu) |
280 | cx88_risc_databuffer(dev->pci, &buf->risc, | 246 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); |
281 | dma->sglist, | 247 | memset(risc, 0, sizeof(*risc)); |
282 | buf->vb.width, buf->vb.height, 0); | 248 | return rc; |
283 | } | 249 | } |
284 | buf->vb.state = VIDEOBUF_PREPARED; | ||
285 | return 0; | 250 | return 0; |
286 | |||
287 | fail: | ||
288 | cx88_free_buffer(q,buf); | ||
289 | return rc; | ||
290 | } | 251 | } |
291 | 252 | ||
292 | void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) | 253 | void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) |
@@ -295,35 +256,33 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf) | |||
295 | struct cx88_dmaqueue *cx88q = &dev->mpegq; | 256 | struct cx88_dmaqueue *cx88q = &dev->mpegq; |
296 | 257 | ||
297 | dprintk( 1, "cx8802_buf_queue\n" ); | 258 | dprintk( 1, "cx8802_buf_queue\n" ); |
298 | /* add jump to stopper */ | 259 | /* add jump to start */ |
299 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 260 | buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8); |
300 | buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma); | 261 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); |
262 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8); | ||
301 | 263 | ||
302 | if (list_empty(&cx88q->active)) { | 264 | if (list_empty(&cx88q->active)) { |
303 | dprintk( 1, "queue is empty - first active\n" ); | 265 | dprintk( 1, "queue is empty - first active\n" ); |
304 | list_add_tail(&buf->vb.queue,&cx88q->active); | 266 | list_add_tail(&buf->list, &cx88q->active); |
305 | cx8802_start_dma(dev, cx88q, buf); | ||
306 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
307 | buf->count = cx88q->count++; | 267 | buf->count = cx88q->count++; |
308 | mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT); | ||
309 | dprintk(1,"[%p/%d] %s - first active\n", | 268 | dprintk(1,"[%p/%d] %s - first active\n", |
310 | buf, buf->vb.i, __func__); | 269 | buf, buf->vb.v4l2_buf.index, __func__); |
311 | 270 | ||
312 | } else { | 271 | } else { |
272 | buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); | ||
313 | dprintk( 1, "queue is not empty - append to active\n" ); | 273 | dprintk( 1, "queue is not empty - append to active\n" ); |
314 | prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue); | 274 | prev = list_entry(cx88q->active.prev, struct cx88_buffer, list); |
315 | list_add_tail(&buf->vb.queue,&cx88q->active); | 275 | list_add_tail(&buf->list, &cx88q->active); |
316 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
317 | buf->count = cx88q->count++; | 276 | buf->count = cx88q->count++; |
318 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 277 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
319 | dprintk( 1, "[%p/%d] %s - append to active\n", | 278 | dprintk( 1, "[%p/%d] %s - append to active\n", |
320 | buf, buf->vb.i, __func__); | 279 | buf, buf->vb.v4l2_buf.index, __func__); |
321 | } | 280 | } |
322 | } | 281 | } |
323 | 282 | ||
324 | /* ----------------------------------------------------------- */ | 283 | /* ----------------------------------------------------------- */ |
325 | 284 | ||
326 | static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart) | 285 | static void do_cancel_buffers(struct cx8802_dev *dev) |
327 | { | 286 | { |
328 | struct cx88_dmaqueue *q = &dev->mpegq; | 287 | struct cx88_dmaqueue *q = &dev->mpegq; |
329 | struct cx88_buffer *buf; | 288 | struct cx88_buffer *buf; |
@@ -331,41 +290,18 @@ static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int re | |||
331 | 290 | ||
332 | spin_lock_irqsave(&dev->slock,flags); | 291 | spin_lock_irqsave(&dev->slock,flags); |
333 | while (!list_empty(&q->active)) { | 292 | while (!list_empty(&q->active)) { |
334 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 293 | buf = list_entry(q->active.next, struct cx88_buffer, list); |
335 | list_del(&buf->vb.queue); | 294 | list_del(&buf->list); |
336 | buf->vb.state = VIDEOBUF_ERROR; | 295 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); |
337 | wake_up(&buf->vb.done); | ||
338 | dprintk(1,"[%p/%d] %s - dma=0x%08lx\n", | ||
339 | buf, buf->vb.i, reason, (unsigned long)buf->risc.dma); | ||
340 | } | ||
341 | if (restart) | ||
342 | { | ||
343 | dprintk(1, "restarting queue\n" ); | ||
344 | cx8802_restart_queue(dev,q); | ||
345 | } | 296 | } |
346 | spin_unlock_irqrestore(&dev->slock,flags); | 297 | spin_unlock_irqrestore(&dev->slock,flags); |
347 | } | 298 | } |
348 | 299 | ||
349 | void cx8802_cancel_buffers(struct cx8802_dev *dev) | 300 | void cx8802_cancel_buffers(struct cx8802_dev *dev) |
350 | { | 301 | { |
351 | struct cx88_dmaqueue *q = &dev->mpegq; | ||
352 | |||
353 | dprintk( 1, "cx8802_cancel_buffers" ); | 302 | dprintk( 1, "cx8802_cancel_buffers" ); |
354 | del_timer_sync(&q->timeout); | ||
355 | cx8802_stop_dma(dev); | 303 | cx8802_stop_dma(dev); |
356 | do_cancel_buffers(dev,"cancel",0); | 304 | do_cancel_buffers(dev); |
357 | } | ||
358 | |||
359 | static void cx8802_timeout(unsigned long data) | ||
360 | { | ||
361 | struct cx8802_dev *dev = (struct cx8802_dev*)data; | ||
362 | |||
363 | dprintk(1, "%s\n",__func__); | ||
364 | |||
365 | if (debug) | ||
366 | cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]); | ||
367 | cx8802_stop_dma(dev); | ||
368 | do_cancel_buffers(dev,"timeout",1); | ||
369 | } | 305 | } |
370 | 306 | ||
371 | static const char * cx88_mpeg_irqs[32] = { | 307 | static const char * cx88_mpeg_irqs[32] = { |
@@ -411,19 +347,11 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) | |||
411 | spin_unlock(&dev->slock); | 347 | spin_unlock(&dev->slock); |
412 | } | 348 | } |
413 | 349 | ||
414 | /* risc2 y */ | ||
415 | if (status & 0x10) { | ||
416 | spin_lock(&dev->slock); | ||
417 | cx8802_restart_queue(dev,&dev->mpegq); | ||
418 | spin_unlock(&dev->slock); | ||
419 | } | ||
420 | |||
421 | /* other general errors */ | 350 | /* other general errors */ |
422 | if (status & 0x1f0100) { | 351 | if (status & 0x1f0100) { |
423 | dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); | 352 | dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); |
424 | spin_lock(&dev->slock); | 353 | spin_lock(&dev->slock); |
425 | cx8802_stop_dma(dev); | 354 | cx8802_stop_dma(dev); |
426 | cx8802_restart_queue(dev,&dev->mpegq); | ||
427 | spin_unlock(&dev->slock); | 355 | spin_unlock(&dev->slock); |
428 | } | 356 | } |
429 | } | 357 | } |
@@ -490,12 +418,6 @@ static int cx8802_init_common(struct cx8802_dev *dev) | |||
490 | 418 | ||
491 | /* init dma queue */ | 419 | /* init dma queue */ |
492 | INIT_LIST_HEAD(&dev->mpegq.active); | 420 | INIT_LIST_HEAD(&dev->mpegq.active); |
493 | INIT_LIST_HEAD(&dev->mpegq.queued); | ||
494 | dev->mpegq.timeout.function = cx8802_timeout; | ||
495 | dev->mpegq.timeout.data = (unsigned long)dev; | ||
496 | init_timer(&dev->mpegq.timeout); | ||
497 | cx88_risc_stopper(dev->pci,&dev->mpegq.stopper, | ||
498 | MO_TS_DMACNTRL,0x11,0x00); | ||
499 | 421 | ||
500 | /* get irq */ | 422 | /* get irq */ |
501 | err = request_irq(dev->pci->irq, cx8802_irq, | 423 | err = request_irq(dev->pci->irq, cx8802_irq, |
@@ -520,9 +442,6 @@ static void cx8802_fini_common(struct cx8802_dev *dev) | |||
520 | 442 | ||
521 | /* unregister stuff */ | 443 | /* unregister stuff */ |
522 | free_irq(dev->pci->irq, dev); | 444 | free_irq(dev->pci->irq, dev); |
523 | |||
524 | /* free memory */ | ||
525 | btcx_riscmem_free(dev->pci,&dev->mpegq.stopper); | ||
526 | } | 445 | } |
527 | 446 | ||
528 | /* ----------------------------------------------------------- */ | 447 | /* ----------------------------------------------------------- */ |
@@ -539,7 +458,6 @@ static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) | |||
539 | dprintk( 2, "suspend\n" ); | 458 | dprintk( 2, "suspend\n" ); |
540 | printk("%s: suspend mpeg\n", core->name); | 459 | printk("%s: suspend mpeg\n", core->name); |
541 | cx8802_stop_dma(dev); | 460 | cx8802_stop_dma(dev); |
542 | del_timer(&dev->mpegq.timeout); | ||
543 | } | 461 | } |
544 | spin_unlock_irqrestore(&dev->slock, flags); | 462 | spin_unlock_irqrestore(&dev->slock, flags); |
545 | 463 | ||
@@ -907,6 +825,7 @@ module_pci_driver(cx8802_pci_driver); | |||
907 | EXPORT_SYMBOL(cx8802_buf_prepare); | 825 | EXPORT_SYMBOL(cx8802_buf_prepare); |
908 | EXPORT_SYMBOL(cx8802_buf_queue); | 826 | EXPORT_SYMBOL(cx8802_buf_queue); |
909 | EXPORT_SYMBOL(cx8802_cancel_buffers); | 827 | EXPORT_SYMBOL(cx8802_cancel_buffers); |
828 | EXPORT_SYMBOL(cx8802_start_dma); | ||
910 | 829 | ||
911 | EXPORT_SYMBOL(cx8802_register_driver); | 830 | EXPORT_SYMBOL(cx8802_register_driver); |
912 | EXPORT_SYMBOL(cx8802_unregister_driver); | 831 | EXPORT_SYMBOL(cx8802_unregister_driver); |
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c index f8f8389c0362..6ab6e27648f6 100644 --- a/drivers/media/pci/cx88/cx88-vbi.c +++ b/drivers/media/pci/cx88/cx88-vbi.c | |||
@@ -6,10 +6,6 @@ | |||
6 | 6 | ||
7 | #include "cx88.h" | 7 | #include "cx88.h" |
8 | 8 | ||
9 | static unsigned int vbibufs = 4; | ||
10 | module_param(vbibufs,int,0644); | ||
11 | MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32"); | ||
12 | |||
13 | static unsigned int vbi_debug; | 9 | static unsigned int vbi_debug; |
14 | module_param(vbi_debug,int,0644); | 10 | module_param(vbi_debug,int,0644); |
15 | MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); | 11 | MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); |
@@ -22,26 +18,27 @@ MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]"); | |||
22 | int cx8800_vbi_fmt (struct file *file, void *priv, | 18 | int cx8800_vbi_fmt (struct file *file, void *priv, |
23 | struct v4l2_format *f) | 19 | struct v4l2_format *f) |
24 | { | 20 | { |
25 | struct cx8800_fh *fh = priv; | 21 | struct cx8800_dev *dev = video_drvdata(file); |
26 | struct cx8800_dev *dev = fh->dev; | ||
27 | 22 | ||
28 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; | 23 | f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH; |
29 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; | 24 | f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; |
30 | f->fmt.vbi.offset = 244; | 25 | f->fmt.vbi.offset = 244; |
31 | f->fmt.vbi.count[0] = VBI_LINE_COUNT; | ||
32 | f->fmt.vbi.count[1] = VBI_LINE_COUNT; | ||
33 | 26 | ||
34 | if (dev->core->tvnorm & V4L2_STD_525_60) { | 27 | if (dev->core->tvnorm & V4L2_STD_525_60) { |
35 | /* ntsc */ | 28 | /* ntsc */ |
36 | f->fmt.vbi.sampling_rate = 28636363; | 29 | f->fmt.vbi.sampling_rate = 28636363; |
37 | f->fmt.vbi.start[0] = 10; | 30 | f->fmt.vbi.start[0] = 10; |
38 | f->fmt.vbi.start[1] = 273; | 31 | f->fmt.vbi.start[1] = 273; |
32 | f->fmt.vbi.count[0] = VBI_LINE_NTSC_COUNT; | ||
33 | f->fmt.vbi.count[1] = VBI_LINE_NTSC_COUNT; | ||
39 | 34 | ||
40 | } else if (dev->core->tvnorm & V4L2_STD_625_50) { | 35 | } else if (dev->core->tvnorm & V4L2_STD_625_50) { |
41 | /* pal */ | 36 | /* pal */ |
42 | f->fmt.vbi.sampling_rate = 35468950; | 37 | f->fmt.vbi.sampling_rate = 35468950; |
43 | f->fmt.vbi.start[0] = 7 -1; | 38 | f->fmt.vbi.start[0] = V4L2_VBI_ITU_625_F1_START + 5; |
44 | f->fmt.vbi.start[1] = 319 -1; | 39 | f->fmt.vbi.start[1] = V4L2_VBI_ITU_625_F2_START + 5; |
40 | f->fmt.vbi.count[0] = VBI_LINE_PAL_COUNT; | ||
41 | f->fmt.vbi.count[1] = VBI_LINE_PAL_COUNT; | ||
45 | } | 42 | } |
46 | return 0; | 43 | return 0; |
47 | } | 44 | } |
@@ -54,7 +51,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev, | |||
54 | 51 | ||
55 | /* setup fifo + format */ | 52 | /* setup fifo + format */ |
56 | cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24], | 53 | cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24], |
57 | buf->vb.width, buf->risc.dma); | 54 | VBI_LINE_LENGTH, buf->risc.dma); |
58 | 55 | ||
59 | cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup | 56 | cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup |
60 | (1 << 15) | // enable vbi capture | 57 | (1 << 15) | // enable vbi capture |
@@ -78,7 +75,7 @@ static int cx8800_start_vbi_dma(struct cx8800_dev *dev, | |||
78 | return 0; | 75 | return 0; |
79 | } | 76 | } |
80 | 77 | ||
81 | int cx8800_stop_vbi_dma(struct cx8800_dev *dev) | 78 | void cx8800_stop_vbi_dma(struct cx8800_dev *dev) |
82 | { | 79 | { |
83 | struct cx88_core *core = dev->core; | 80 | struct cx88_core *core = dev->core; |
84 | 81 | ||
@@ -91,7 +88,6 @@ int cx8800_stop_vbi_dma(struct cx8800_dev *dev) | |||
91 | /* disable irqs */ | 88 | /* disable irqs */ |
92 | cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); | 89 | cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT); |
93 | cx_clear(MO_VID_INTMSK, 0x0f0088); | 90 | cx_clear(MO_VID_INTMSK, 0x0f0088); |
94 | return 0; | ||
95 | } | 91 | } |
96 | 92 | ||
97 | int cx8800_restart_vbi_queue(struct cx8800_dev *dev, | 93 | int cx8800_restart_vbi_queue(struct cx8800_dev *dev, |
@@ -102,144 +98,144 @@ int cx8800_restart_vbi_queue(struct cx8800_dev *dev, | |||
102 | if (list_empty(&q->active)) | 98 | if (list_empty(&q->active)) |
103 | return 0; | 99 | return 0; |
104 | 100 | ||
105 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 101 | buf = list_entry(q->active.next, struct cx88_buffer, list); |
106 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 102 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
107 | buf, buf->vb.i); | 103 | buf, buf->vb.v4l2_buf.index); |
108 | cx8800_start_vbi_dma(dev, q, buf); | 104 | cx8800_start_vbi_dma(dev, q, buf); |
109 | list_for_each_entry(buf, &q->active, vb.queue) | 105 | list_for_each_entry(buf, &q->active, list) |
110 | buf->count = q->count++; | 106 | buf->count = q->count++; |
111 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
112 | return 0; | 107 | return 0; |
113 | } | 108 | } |
114 | 109 | ||
115 | void cx8800_vbi_timeout(unsigned long data) | ||
116 | { | ||
117 | struct cx8800_dev *dev = (struct cx8800_dev*)data; | ||
118 | struct cx88_core *core = dev->core; | ||
119 | struct cx88_dmaqueue *q = &dev->vbiq; | ||
120 | struct cx88_buffer *buf; | ||
121 | unsigned long flags; | ||
122 | |||
123 | cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]); | ||
124 | |||
125 | cx_clear(MO_VID_DMACNTRL, 0x88); | ||
126 | cx_clear(VID_CAPTURE_CONTROL, 0x18); | ||
127 | |||
128 | spin_lock_irqsave(&dev->slock,flags); | ||
129 | while (!list_empty(&q->active)) { | ||
130 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | ||
131 | list_del(&buf->vb.queue); | ||
132 | buf->vb.state = VIDEOBUF_ERROR; | ||
133 | wake_up(&buf->vb.done); | ||
134 | printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name, | ||
135 | buf, buf->vb.i, (unsigned long)buf->risc.dma); | ||
136 | } | ||
137 | cx8800_restart_vbi_queue(dev,q); | ||
138 | spin_unlock_irqrestore(&dev->slock,flags); | ||
139 | } | ||
140 | |||
141 | /* ------------------------------------------------------------------ */ | 110 | /* ------------------------------------------------------------------ */ |
142 | 111 | ||
143 | static int | 112 | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
144 | vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | 113 | unsigned int *num_buffers, unsigned int *num_planes, |
114 | unsigned int sizes[], void *alloc_ctxs[]) | ||
145 | { | 115 | { |
146 | *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; | 116 | struct cx8800_dev *dev = q->drv_priv; |
147 | if (0 == *count) | 117 | |
148 | *count = vbibufs; | 118 | *num_planes = 1; |
149 | if (*count < 2) | 119 | if (dev->core->tvnorm & V4L2_STD_525_60) |
150 | *count = 2; | 120 | sizes[0] = VBI_LINE_NTSC_COUNT * VBI_LINE_LENGTH * 2; |
151 | if (*count > 32) | 121 | else |
152 | *count = 32; | 122 | sizes[0] = VBI_LINE_PAL_COUNT * VBI_LINE_LENGTH * 2; |
153 | return 0; | 123 | return 0; |
154 | } | 124 | } |
155 | 125 | ||
156 | static int | 126 | |
157 | vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 127 | static int buffer_prepare(struct vb2_buffer *vb) |
158 | enum v4l2_field field) | ||
159 | { | 128 | { |
160 | struct cx8800_fh *fh = q->priv_data; | 129 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
161 | struct cx8800_dev *dev = fh->dev; | 130 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
162 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 131 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); |
132 | unsigned int lines; | ||
163 | unsigned int size; | 133 | unsigned int size; |
164 | int rc; | 134 | int rc; |
165 | 135 | ||
166 | size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2; | 136 | if (dev->core->tvnorm & V4L2_STD_525_60) |
167 | if (0 != buf->vb.baddr && buf->vb.bsize < size) | 137 | lines = VBI_LINE_NTSC_COUNT; |
138 | else | ||
139 | lines = VBI_LINE_PAL_COUNT; | ||
140 | size = lines * VBI_LINE_LENGTH * 2; | ||
141 | if (vb2_plane_size(vb, 0) < size) | ||
168 | return -EINVAL; | 142 | return -EINVAL; |
143 | vb2_set_plane_payload(vb, 0, size); | ||
169 | 144 | ||
170 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 145 | rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); |
171 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | 146 | if (!rc) |
172 | buf->vb.width = VBI_LINE_LENGTH; | 147 | return -EIO; |
173 | buf->vb.height = VBI_LINE_COUNT; | 148 | |
174 | buf->vb.size = size; | 149 | cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl, |
175 | buf->vb.field = V4L2_FIELD_SEQ_TB; | 150 | 0, VBI_LINE_LENGTH * lines, |
176 | 151 | VBI_LINE_LENGTH, 0, | |
177 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) | 152 | lines); |
178 | goto fail; | ||
179 | cx88_risc_buffer(dev->pci, &buf->risc, | ||
180 | dma->sglist, | ||
181 | 0, buf->vb.width * buf->vb.height, | ||
182 | buf->vb.width, 0, | ||
183 | buf->vb.height); | ||
184 | } | ||
185 | buf->vb.state = VIDEOBUF_PREPARED; | ||
186 | return 0; | 153 | return 0; |
154 | } | ||
187 | 155 | ||
188 | fail: | 156 | static void buffer_finish(struct vb2_buffer *vb) |
189 | cx88_free_buffer(q,buf); | 157 | { |
190 | return rc; | 158 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
159 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
160 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||
161 | struct cx88_riscmem *risc = &buf->risc; | ||
162 | |||
163 | if (risc->cpu) | ||
164 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); | ||
165 | memset(risc, 0, sizeof(*risc)); | ||
166 | |||
167 | dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); | ||
191 | } | 168 | } |
192 | 169 | ||
193 | static void | 170 | static void buffer_queue(struct vb2_buffer *vb) |
194 | vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
195 | { | 171 | { |
196 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 172 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
173 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
197 | struct cx88_buffer *prev; | 174 | struct cx88_buffer *prev; |
198 | struct cx8800_fh *fh = vq->priv_data; | ||
199 | struct cx8800_dev *dev = fh->dev; | ||
200 | struct cx88_dmaqueue *q = &dev->vbiq; | 175 | struct cx88_dmaqueue *q = &dev->vbiq; |
201 | 176 | ||
202 | /* add jump to stopper */ | 177 | /* add jump to start */ |
203 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 178 | buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8); |
204 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | 179 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); |
180 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8); | ||
205 | 181 | ||
206 | if (list_empty(&q->active)) { | 182 | if (list_empty(&q->active)) { |
207 | list_add_tail(&buf->vb.queue,&q->active); | 183 | list_add_tail(&buf->list, &q->active); |
208 | cx8800_start_vbi_dma(dev, q, buf); | 184 | cx8800_start_vbi_dma(dev, q, buf); |
209 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
210 | buf->count = q->count++; | 185 | buf->count = q->count++; |
211 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
212 | dprintk(2,"[%p/%d] vbi_queue - first active\n", | 186 | dprintk(2,"[%p/%d] vbi_queue - first active\n", |
213 | buf, buf->vb.i); | 187 | buf, buf->vb.v4l2_buf.index); |
214 | 188 | ||
215 | } else { | 189 | } else { |
216 | prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); | 190 | buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); |
217 | list_add_tail(&buf->vb.queue,&q->active); | 191 | prev = list_entry(q->active.prev, struct cx88_buffer, list); |
218 | buf->vb.state = VIDEOBUF_ACTIVE; | 192 | list_add_tail(&buf->list, &q->active); |
219 | buf->count = q->count++; | 193 | buf->count = q->count++; |
220 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 194 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
221 | dprintk(2,"[%p/%d] buffer_queue - append to active\n", | 195 | dprintk(2,"[%p/%d] buffer_queue - append to active\n", |
222 | buf, buf->vb.i); | 196 | buf, buf->vb.v4l2_buf.index); |
223 | } | 197 | } |
224 | } | 198 | } |
225 | 199 | ||
226 | static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 200 | static int start_streaming(struct vb2_queue *q, unsigned int count) |
227 | { | 201 | { |
228 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 202 | struct cx8800_dev *dev = q->drv_priv; |
203 | struct cx88_dmaqueue *dmaq = &dev->vbiq; | ||
204 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
205 | struct cx88_buffer, list); | ||
229 | 206 | ||
230 | cx88_free_buffer(q,buf); | 207 | cx8800_start_vbi_dma(dev, dmaq, buf); |
208 | return 0; | ||
231 | } | 209 | } |
232 | 210 | ||
233 | const struct videobuf_queue_ops cx8800_vbi_qops = { | 211 | static void stop_streaming(struct vb2_queue *q) |
234 | .buf_setup = vbi_setup, | 212 | { |
235 | .buf_prepare = vbi_prepare, | 213 | struct cx8800_dev *dev = q->drv_priv; |
236 | .buf_queue = vbi_queue, | 214 | struct cx88_core *core = dev->core; |
237 | .buf_release = vbi_release, | 215 | struct cx88_dmaqueue *dmaq = &dev->vbiq; |
238 | }; | 216 | unsigned long flags; |
239 | 217 | ||
240 | /* ------------------------------------------------------------------ */ | 218 | cx_clear(MO_VID_DMACNTRL, 0x11); |
241 | /* | 219 | cx_clear(VID_CAPTURE_CONTROL, 0x06); |
242 | * Local variables: | 220 | cx8800_stop_vbi_dma(dev); |
243 | * c-basic-offset: 8 | 221 | spin_lock_irqsave(&dev->slock, flags); |
244 | * End: | 222 | while (!list_empty(&dmaq->active)) { |
245 | */ | 223 | struct cx88_buffer *buf = list_entry(dmaq->active.next, |
224 | struct cx88_buffer, list); | ||
225 | |||
226 | list_del(&buf->list); | ||
227 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
228 | } | ||
229 | spin_unlock_irqrestore(&dev->slock, flags); | ||
230 | } | ||
231 | |||
232 | const struct vb2_ops cx8800_vbi_qops = { | ||
233 | .queue_setup = queue_setup, | ||
234 | .buf_prepare = buffer_prepare, | ||
235 | .buf_finish = buffer_finish, | ||
236 | .buf_queue = buffer_queue, | ||
237 | .wait_prepare = vb2_ops_wait_prepare, | ||
238 | .wait_finish = vb2_ops_wait_finish, | ||
239 | .start_streaming = start_streaming, | ||
240 | .stop_streaming = stop_streaming, | ||
241 | }; | ||
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index ce27e6d4f16e..a64ae31ae142 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c | |||
@@ -70,10 +70,6 @@ static unsigned int irq_debug; | |||
70 | module_param(irq_debug,int,0644); | 70 | module_param(irq_debug,int,0644); |
71 | MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); | 71 | MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); |
72 | 72 | ||
73 | static unsigned int vid_limit = 16; | ||
74 | module_param(vid_limit,int,0644); | ||
75 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
76 | |||
77 | #define dprintk(level,fmt, arg...) if (video_debug >= level) \ | 73 | #define dprintk(level,fmt, arg...) if (video_debug >= level) \ |
78 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) | 74 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) |
79 | 75 | ||
@@ -297,56 +293,6 @@ enum { | |||
297 | CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls), | 293 | CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls), |
298 | }; | 294 | }; |
299 | 295 | ||
300 | /* ------------------------------------------------------------------- */ | ||
301 | /* resource management */ | ||
302 | |||
303 | static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit) | ||
304 | { | ||
305 | struct cx88_core *core = dev->core; | ||
306 | if (fh->resources & bit) | ||
307 | /* have it already allocated */ | ||
308 | return 1; | ||
309 | |||
310 | /* is it free? */ | ||
311 | mutex_lock(&core->lock); | ||
312 | if (dev->resources & bit) { | ||
313 | /* no, someone else uses it */ | ||
314 | mutex_unlock(&core->lock); | ||
315 | return 0; | ||
316 | } | ||
317 | /* it's free, grab it */ | ||
318 | fh->resources |= bit; | ||
319 | dev->resources |= bit; | ||
320 | dprintk(1,"res: get %d\n",bit); | ||
321 | mutex_unlock(&core->lock); | ||
322 | return 1; | ||
323 | } | ||
324 | |||
325 | static | ||
326 | int res_check(struct cx8800_fh *fh, unsigned int bit) | ||
327 | { | ||
328 | return (fh->resources & bit); | ||
329 | } | ||
330 | |||
331 | static | ||
332 | int res_locked(struct cx8800_dev *dev, unsigned int bit) | ||
333 | { | ||
334 | return (dev->resources & bit); | ||
335 | } | ||
336 | |||
337 | static | ||
338 | void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) | ||
339 | { | ||
340 | struct cx88_core *core = dev->core; | ||
341 | BUG_ON((fh->resources & bits) != bits); | ||
342 | |||
343 | mutex_lock(&core->lock); | ||
344 | fh->resources &= ~bits; | ||
345 | dev->resources &= ~bits; | ||
346 | dprintk(1,"res: put %d\n",bits); | ||
347 | mutex_unlock(&core->lock); | ||
348 | } | ||
349 | |||
350 | /* ------------------------------------------------------------------ */ | 296 | /* ------------------------------------------------------------------ */ |
351 | 297 | ||
352 | int cx88_video_mux(struct cx88_core *core, unsigned int input) | 298 | int cx88_video_mux(struct cx88_core *core, unsigned int input) |
@@ -419,8 +365,8 @@ static int start_video_dma(struct cx8800_dev *dev, | |||
419 | /* setup fifo + format */ | 365 | /* setup fifo + format */ |
420 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], | 366 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], |
421 | buf->bpl, buf->risc.dma); | 367 | buf->bpl, buf->risc.dma); |
422 | cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field); | 368 | cx88_set_scale(core, core->width, core->height, core->field); |
423 | cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma); | 369 | cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma); |
424 | 370 | ||
425 | /* reset counter */ | 371 | /* reset counter */ |
426 | cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET); | 372 | cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET); |
@@ -470,433 +416,211 @@ static int restart_video_queue(struct cx8800_dev *dev, | |||
470 | struct cx88_dmaqueue *q) | 416 | struct cx88_dmaqueue *q) |
471 | { | 417 | { |
472 | struct cx88_core *core = dev->core; | 418 | struct cx88_core *core = dev->core; |
473 | struct cx88_buffer *buf, *prev; | 419 | struct cx88_buffer *buf; |
474 | 420 | ||
475 | if (!list_empty(&q->active)) { | 421 | if (!list_empty(&q->active)) { |
476 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 422 | buf = list_entry(q->active.next, struct cx88_buffer, list); |
477 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 423 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
478 | buf, buf->vb.i); | 424 | buf, buf->vb.v4l2_buf.index); |
479 | start_video_dma(dev, q, buf); | 425 | start_video_dma(dev, q, buf); |
480 | list_for_each_entry(buf, &q->active, vb.queue) | 426 | list_for_each_entry(buf, &q->active, list) |
481 | buf->count = q->count++; | 427 | buf->count = q->count++; |
482 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | prev = NULL; | ||
487 | for (;;) { | ||
488 | if (list_empty(&q->queued)) | ||
489 | return 0; | ||
490 | buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); | ||
491 | if (NULL == prev) { | ||
492 | list_move_tail(&buf->vb.queue, &q->active); | ||
493 | start_video_dma(dev, q, buf); | ||
494 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
495 | buf->count = q->count++; | ||
496 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
497 | dprintk(2,"[%p/%d] restart_queue - first active\n", | ||
498 | buf,buf->vb.i); | ||
499 | |||
500 | } else if (prev->vb.width == buf->vb.width && | ||
501 | prev->vb.height == buf->vb.height && | ||
502 | prev->fmt == buf->fmt) { | ||
503 | list_move_tail(&buf->vb.queue, &q->active); | ||
504 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
505 | buf->count = q->count++; | ||
506 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
507 | dprintk(2,"[%p/%d] restart_queue - move to active\n", | ||
508 | buf,buf->vb.i); | ||
509 | } else { | ||
510 | return 0; | ||
511 | } | ||
512 | prev = buf; | ||
513 | } | 428 | } |
429 | return 0; | ||
514 | } | 430 | } |
515 | 431 | ||
516 | /* ------------------------------------------------------------------ */ | 432 | /* ------------------------------------------------------------------ */ |
517 | 433 | ||
518 | static int | 434 | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
519 | buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | 435 | unsigned int *num_buffers, unsigned int *num_planes, |
436 | unsigned int sizes[], void *alloc_ctxs[]) | ||
520 | { | 437 | { |
521 | struct cx8800_fh *fh = q->priv_data; | 438 | struct cx8800_dev *dev = q->drv_priv; |
522 | struct cx8800_dev *dev = fh->dev; | 439 | struct cx88_core *core = dev->core; |
523 | 440 | ||
524 | *size = dev->fmt->depth * dev->width * dev->height >> 3; | 441 | *num_planes = 1; |
525 | if (0 == *count) | 442 | sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3; |
526 | *count = 32; | ||
527 | if (*size * *count > vid_limit * 1024 * 1024) | ||
528 | *count = (vid_limit * 1024 * 1024) / *size; | ||
529 | return 0; | 443 | return 0; |
530 | } | 444 | } |
531 | 445 | ||
532 | static int | 446 | static int buffer_prepare(struct vb2_buffer *vb) |
533 | buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
534 | enum v4l2_field field) | ||
535 | { | 447 | { |
536 | struct cx8800_fh *fh = q->priv_data; | 448 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
537 | struct cx8800_dev *dev = fh->dev; | ||
538 | struct cx88_core *core = dev->core; | 449 | struct cx88_core *core = dev->core; |
539 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 450 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
540 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | 451 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); |
541 | int rc, init_buffer = 0; | 452 | int rc; |
542 | 453 | ||
543 | BUG_ON(NULL == dev->fmt); | 454 | buf->bpl = core->width * dev->fmt->depth >> 3; |
544 | if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) || | ||
545 | dev->height < 32 || dev->height > norm_maxh(core->tvnorm)) | ||
546 | return -EINVAL; | ||
547 | buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3; | ||
548 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
549 | return -EINVAL; | ||
550 | 455 | ||
551 | if (buf->fmt != dev->fmt || | 456 | if (vb2_plane_size(vb, 0) < core->height * buf->bpl) |
552 | buf->vb.width != dev->width || | 457 | return -EINVAL; |
553 | buf->vb.height != dev->height || | 458 | vb2_set_plane_payload(vb, 0, core->height * buf->bpl); |
554 | buf->vb.field != field) { | ||
555 | buf->fmt = dev->fmt; | ||
556 | buf->vb.width = dev->width; | ||
557 | buf->vb.height = dev->height; | ||
558 | buf->vb.field = field; | ||
559 | init_buffer = 1; | ||
560 | } | ||
561 | 459 | ||
562 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 460 | rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); |
563 | init_buffer = 1; | 461 | if (!rc) |
564 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) | 462 | return -EIO; |
565 | goto fail; | ||
566 | } | ||
567 | 463 | ||
568 | if (init_buffer) { | 464 | switch (core->field) { |
569 | buf->bpl = buf->vb.width * buf->fmt->depth >> 3; | 465 | case V4L2_FIELD_TOP: |
570 | switch (buf->vb.field) { | 466 | cx88_risc_buffer(dev->pci, &buf->risc, |
571 | case V4L2_FIELD_TOP: | 467 | sgt->sgl, 0, UNSET, |
572 | cx88_risc_buffer(dev->pci, &buf->risc, | 468 | buf->bpl, 0, core->height); |
573 | dma->sglist, 0, UNSET, | 469 | break; |
574 | buf->bpl, 0, buf->vb.height); | 470 | case V4L2_FIELD_BOTTOM: |
575 | break; | 471 | cx88_risc_buffer(dev->pci, &buf->risc, |
576 | case V4L2_FIELD_BOTTOM: | 472 | sgt->sgl, UNSET, 0, |
577 | cx88_risc_buffer(dev->pci, &buf->risc, | 473 | buf->bpl, 0, core->height); |
578 | dma->sglist, UNSET, 0, | 474 | break; |
579 | buf->bpl, 0, buf->vb.height); | 475 | case V4L2_FIELD_SEQ_TB: |
580 | break; | 476 | cx88_risc_buffer(dev->pci, &buf->risc, |
581 | case V4L2_FIELD_INTERLACED: | 477 | sgt->sgl, |
582 | cx88_risc_buffer(dev->pci, &buf->risc, | 478 | 0, buf->bpl * (core->height >> 1), |
583 | dma->sglist, 0, buf->bpl, | 479 | buf->bpl, 0, |
584 | buf->bpl, buf->bpl, | 480 | core->height >> 1); |
585 | buf->vb.height >> 1); | 481 | break; |
586 | break; | 482 | case V4L2_FIELD_SEQ_BT: |
587 | case V4L2_FIELD_SEQ_TB: | 483 | cx88_risc_buffer(dev->pci, &buf->risc, |
588 | cx88_risc_buffer(dev->pci, &buf->risc, | 484 | sgt->sgl, |
589 | dma->sglist, | 485 | buf->bpl * (core->height >> 1), 0, |
590 | 0, buf->bpl * (buf->vb.height >> 1), | 486 | buf->bpl, 0, |
591 | buf->bpl, 0, | 487 | core->height >> 1); |
592 | buf->vb.height >> 1); | 488 | break; |
593 | break; | 489 | case V4L2_FIELD_INTERLACED: |
594 | case V4L2_FIELD_SEQ_BT: | 490 | default: |
595 | cx88_risc_buffer(dev->pci, &buf->risc, | 491 | cx88_risc_buffer(dev->pci, &buf->risc, |
596 | dma->sglist, | 492 | sgt->sgl, 0, buf->bpl, |
597 | buf->bpl * (buf->vb.height >> 1), 0, | 493 | buf->bpl, buf->bpl, |
598 | buf->bpl, 0, | 494 | core->height >> 1); |
599 | buf->vb.height >> 1); | 495 | break; |
600 | break; | ||
601 | default: | ||
602 | BUG(); | ||
603 | } | ||
604 | } | 496 | } |
605 | dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", | 497 | dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", |
606 | buf, buf->vb.i, | 498 | buf, buf->vb.v4l2_buf.index, |
607 | dev->width, dev->height, dev->fmt->depth, dev->fmt->name, | 499 | core->width, core->height, dev->fmt->depth, dev->fmt->name, |
608 | (unsigned long)buf->risc.dma); | 500 | (unsigned long)buf->risc.dma); |
609 | |||
610 | buf->vb.state = VIDEOBUF_PREPARED; | ||
611 | return 0; | 501 | return 0; |
502 | } | ||
503 | |||
504 | static void buffer_finish(struct vb2_buffer *vb) | ||
505 | { | ||
506 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; | ||
507 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
508 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||
509 | struct cx88_riscmem *risc = &buf->risc; | ||
510 | |||
511 | if (risc->cpu) | ||
512 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); | ||
513 | memset(risc, 0, sizeof(*risc)); | ||
612 | 514 | ||
613 | fail: | 515 | dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); |
614 | cx88_free_buffer(q,buf); | ||
615 | return rc; | ||
616 | } | 516 | } |
617 | 517 | ||
618 | static void | 518 | static void buffer_queue(struct vb2_buffer *vb) |
619 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
620 | { | 519 | { |
621 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 520 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
521 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
622 | struct cx88_buffer *prev; | 522 | struct cx88_buffer *prev; |
623 | struct cx8800_fh *fh = vq->priv_data; | ||
624 | struct cx8800_dev *dev = fh->dev; | ||
625 | struct cx88_core *core = dev->core; | 523 | struct cx88_core *core = dev->core; |
626 | struct cx88_dmaqueue *q = &dev->vidq; | 524 | struct cx88_dmaqueue *q = &dev->vidq; |
627 | 525 | ||
628 | /* add jump to stopper */ | 526 | /* add jump to start */ |
629 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 527 | buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8); |
630 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | 528 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); |
529 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8); | ||
631 | 530 | ||
632 | if (!list_empty(&q->queued)) { | 531 | if (list_empty(&q->active)) { |
633 | list_add_tail(&buf->vb.queue,&q->queued); | 532 | list_add_tail(&buf->list, &q->active); |
634 | buf->vb.state = VIDEOBUF_QUEUED; | ||
635 | dprintk(2,"[%p/%d] buffer_queue - append to queued\n", | ||
636 | buf, buf->vb.i); | ||
637 | |||
638 | } else if (list_empty(&q->active)) { | ||
639 | list_add_tail(&buf->vb.queue,&q->active); | ||
640 | start_video_dma(dev, q, buf); | 533 | start_video_dma(dev, q, buf); |
641 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
642 | buf->count = q->count++; | 534 | buf->count = q->count++; |
643 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
644 | dprintk(2,"[%p/%d] buffer_queue - first active\n", | 535 | dprintk(2,"[%p/%d] buffer_queue - first active\n", |
645 | buf, buf->vb.i); | 536 | buf, buf->vb.v4l2_buf.index); |
646 | 537 | ||
647 | } else { | 538 | } else { |
648 | prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); | 539 | buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); |
649 | if (prev->vb.width == buf->vb.width && | 540 | prev = list_entry(q->active.prev, struct cx88_buffer, list); |
650 | prev->vb.height == buf->vb.height && | 541 | list_add_tail(&buf->list, &q->active); |
651 | prev->fmt == buf->fmt) { | 542 | buf->count = q->count++; |
652 | list_add_tail(&buf->vb.queue,&q->active); | 543 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
653 | buf->vb.state = VIDEOBUF_ACTIVE; | 544 | dprintk(2, "[%p/%d] buffer_queue - append to active\n", |
654 | buf->count = q->count++; | 545 | buf, buf->vb.v4l2_buf.index); |
655 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
656 | dprintk(2,"[%p/%d] buffer_queue - append to active\n", | ||
657 | buf, buf->vb.i); | ||
658 | |||
659 | } else { | ||
660 | list_add_tail(&buf->vb.queue,&q->queued); | ||
661 | buf->vb.state = VIDEOBUF_QUEUED; | ||
662 | dprintk(2,"[%p/%d] buffer_queue - first queued\n", | ||
663 | buf, buf->vb.i); | ||
664 | } | ||
665 | } | 546 | } |
666 | } | 547 | } |
667 | 548 | ||
668 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 549 | static int start_streaming(struct vb2_queue *q, unsigned int count) |
669 | { | 550 | { |
670 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 551 | struct cx8800_dev *dev = q->drv_priv; |
552 | struct cx88_dmaqueue *dmaq = &dev->vidq; | ||
553 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
554 | struct cx88_buffer, list); | ||
671 | 555 | ||
672 | cx88_free_buffer(q,buf); | 556 | start_video_dma(dev, dmaq, buf); |
557 | return 0; | ||
673 | } | 558 | } |
674 | 559 | ||
675 | static const struct videobuf_queue_ops cx8800_video_qops = { | 560 | static void stop_streaming(struct vb2_queue *q) |
676 | .buf_setup = buffer_setup, | ||
677 | .buf_prepare = buffer_prepare, | ||
678 | .buf_queue = buffer_queue, | ||
679 | .buf_release = buffer_release, | ||
680 | }; | ||
681 | |||
682 | /* ------------------------------------------------------------------ */ | ||
683 | |||
684 | |||
685 | /* ------------------------------------------------------------------ */ | ||
686 | |||
687 | static struct videobuf_queue *get_queue(struct file *file) | ||
688 | { | 561 | { |
689 | struct video_device *vdev = video_devdata(file); | 562 | struct cx8800_dev *dev = q->drv_priv; |
690 | struct cx8800_fh *fh = file->private_data; | 563 | struct cx88_core *core = dev->core; |
564 | struct cx88_dmaqueue *dmaq = &dev->vidq; | ||
565 | unsigned long flags; | ||
691 | 566 | ||
692 | switch (vdev->vfl_type) { | 567 | cx_clear(MO_VID_DMACNTRL, 0x11); |
693 | case VFL_TYPE_GRABBER: | 568 | cx_clear(VID_CAPTURE_CONTROL, 0x06); |
694 | return &fh->vidq; | 569 | spin_lock_irqsave(&dev->slock, flags); |
695 | case VFL_TYPE_VBI: | 570 | while (!list_empty(&dmaq->active)) { |
696 | return &fh->vbiq; | 571 | struct cx88_buffer *buf = list_entry(dmaq->active.next, |
697 | default: | 572 | struct cx88_buffer, list); |
698 | BUG(); | 573 | |
574 | list_del(&buf->list); | ||
575 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
699 | } | 576 | } |
577 | spin_unlock_irqrestore(&dev->slock, flags); | ||
700 | } | 578 | } |
701 | 579 | ||
702 | static int get_resource(struct file *file) | 580 | static struct vb2_ops cx8800_video_qops = { |
703 | { | 581 | .queue_setup = queue_setup, |
704 | struct video_device *vdev = video_devdata(file); | 582 | .buf_prepare = buffer_prepare, |
583 | .buf_finish = buffer_finish, | ||
584 | .buf_queue = buffer_queue, | ||
585 | .wait_prepare = vb2_ops_wait_prepare, | ||
586 | .wait_finish = vb2_ops_wait_finish, | ||
587 | .start_streaming = start_streaming, | ||
588 | .stop_streaming = stop_streaming, | ||
589 | }; | ||
705 | 590 | ||
706 | switch (vdev->vfl_type) { | 591 | /* ------------------------------------------------------------------ */ |
707 | case VFL_TYPE_GRABBER: | ||
708 | return RESOURCE_VIDEO; | ||
709 | case VFL_TYPE_VBI: | ||
710 | return RESOURCE_VBI; | ||
711 | default: | ||
712 | BUG(); | ||
713 | } | ||
714 | } | ||
715 | 592 | ||
716 | static int video_open(struct file *file) | 593 | static int radio_open(struct file *file) |
717 | { | 594 | { |
718 | struct video_device *vdev = video_devdata(file); | ||
719 | struct cx8800_dev *dev = video_drvdata(file); | 595 | struct cx8800_dev *dev = video_drvdata(file); |
720 | struct cx88_core *core = dev->core; | 596 | struct cx88_core *core = dev->core; |
721 | struct cx8800_fh *fh; | 597 | int ret = v4l2_fh_open(file); |
722 | enum v4l2_buf_type type = 0; | ||
723 | int radio = 0; | ||
724 | 598 | ||
725 | switch (vdev->vfl_type) { | 599 | if (ret) |
726 | case VFL_TYPE_GRABBER: | 600 | return ret; |
727 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
728 | break; | ||
729 | case VFL_TYPE_VBI: | ||
730 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
731 | break; | ||
732 | case VFL_TYPE_RADIO: | ||
733 | radio = 1; | ||
734 | break; | ||
735 | } | ||
736 | |||
737 | dprintk(1, "open dev=%s radio=%d type=%s\n", | ||
738 | video_device_node_name(vdev), radio, v4l2_type_names[type]); | ||
739 | |||
740 | /* allocate + initialize per filehandle data */ | ||
741 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | ||
742 | if (unlikely(!fh)) | ||
743 | return -ENOMEM; | ||
744 | |||
745 | v4l2_fh_init(&fh->fh, vdev); | ||
746 | file->private_data = fh; | ||
747 | fh->dev = dev; | ||
748 | 601 | ||
749 | mutex_lock(&core->lock); | 602 | cx_write(MO_GP3_IO, core->board.radio.gpio3); |
750 | 603 | cx_write(MO_GP0_IO, core->board.radio.gpio0); | |
751 | videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, | 604 | cx_write(MO_GP1_IO, core->board.radio.gpio1); |
752 | &dev->pci->dev, &dev->slock, | 605 | cx_write(MO_GP2_IO, core->board.radio.gpio2); |
753 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 606 | if (core->board.radio.audioroute) { |
754 | V4L2_FIELD_INTERLACED, | 607 | if (core->sd_wm8775) { |
755 | sizeof(struct cx88_buffer), | 608 | call_all(core, audio, s_routing, |
756 | fh, NULL); | ||
757 | videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, | ||
758 | &dev->pci->dev, &dev->slock, | ||
759 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
760 | V4L2_FIELD_SEQ_TB, | ||
761 | sizeof(struct cx88_buffer), | ||
762 | fh, NULL); | ||
763 | |||
764 | if (vdev->vfl_type == VFL_TYPE_RADIO) { | ||
765 | dprintk(1,"video_open: setting radio device\n"); | ||
766 | cx_write(MO_GP3_IO, core->board.radio.gpio3); | ||
767 | cx_write(MO_GP0_IO, core->board.radio.gpio0); | ||
768 | cx_write(MO_GP1_IO, core->board.radio.gpio1); | ||
769 | cx_write(MO_GP2_IO, core->board.radio.gpio2); | ||
770 | if (core->board.radio.audioroute) { | ||
771 | if (core->sd_wm8775) { | ||
772 | call_all(core, audio, s_routing, | ||
773 | core->board.radio.audioroute, 0, 0); | 609 | core->board.radio.audioroute, 0, 0); |
774 | } | ||
775 | /* "I2S ADC mode" */ | ||
776 | core->tvaudio = WW_I2SADC; | ||
777 | cx88_set_tvaudio(core); | ||
778 | } else { | ||
779 | /* FM Mode */ | ||
780 | core->tvaudio = WW_FM; | ||
781 | cx88_set_tvaudio(core); | ||
782 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | ||
783 | } | 610 | } |
784 | call_all(core, tuner, s_radio); | 611 | /* "I2S ADC mode" */ |
785 | } | 612 | core->tvaudio = WW_I2SADC; |
786 | 613 | cx88_set_tvaudio(core); | |
787 | core->users++; | ||
788 | mutex_unlock(&core->lock); | ||
789 | v4l2_fh_add(&fh->fh); | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static ssize_t | ||
795 | video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
796 | { | ||
797 | struct video_device *vdev = video_devdata(file); | ||
798 | struct cx8800_fh *fh = file->private_data; | ||
799 | |||
800 | switch (vdev->vfl_type) { | ||
801 | case VFL_TYPE_GRABBER: | ||
802 | if (res_locked(fh->dev,RESOURCE_VIDEO)) | ||
803 | return -EBUSY; | ||
804 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
805 | file->f_flags & O_NONBLOCK); | ||
806 | case VFL_TYPE_VBI: | ||
807 | if (!res_get(fh->dev,fh,RESOURCE_VBI)) | ||
808 | return -EBUSY; | ||
809 | return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1, | ||
810 | file->f_flags & O_NONBLOCK); | ||
811 | default: | ||
812 | BUG(); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | static unsigned int | ||
817 | video_poll(struct file *file, struct poll_table_struct *wait) | ||
818 | { | ||
819 | struct video_device *vdev = video_devdata(file); | ||
820 | struct cx8800_fh *fh = file->private_data; | ||
821 | struct cx88_buffer *buf; | ||
822 | unsigned int rc = v4l2_ctrl_poll(file, wait); | ||
823 | |||
824 | if (vdev->vfl_type == VFL_TYPE_VBI) { | ||
825 | if (!res_get(fh->dev,fh,RESOURCE_VBI)) | ||
826 | return rc | POLLERR; | ||
827 | return rc | videobuf_poll_stream(file, &fh->vbiq, wait); | ||
828 | } | ||
829 | mutex_lock(&fh->vidq.vb_lock); | ||
830 | if (res_check(fh,RESOURCE_VIDEO)) { | ||
831 | /* streaming capture */ | ||
832 | if (list_empty(&fh->vidq.stream)) | ||
833 | goto done; | ||
834 | buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream); | ||
835 | } else { | 614 | } else { |
836 | /* read() capture */ | 615 | /* FM Mode */ |
837 | buf = (struct cx88_buffer*)fh->vidq.read_buf; | 616 | core->tvaudio = WW_FM; |
838 | if (NULL == buf) | 617 | cx88_set_tvaudio(core); |
839 | goto done; | 618 | cx88_set_stereo(core, V4L2_TUNER_MODE_STEREO, 1); |
840 | } | ||
841 | poll_wait(file, &buf->vb.done, wait); | ||
842 | if (buf->vb.state == VIDEOBUF_DONE || | ||
843 | buf->vb.state == VIDEOBUF_ERROR) | ||
844 | rc |= POLLIN|POLLRDNORM; | ||
845 | done: | ||
846 | mutex_unlock(&fh->vidq.vb_lock); | ||
847 | return rc; | ||
848 | } | ||
849 | |||
850 | static int video_release(struct file *file) | ||
851 | { | ||
852 | struct cx8800_fh *fh = file->private_data; | ||
853 | struct cx8800_dev *dev = fh->dev; | ||
854 | |||
855 | /* turn off overlay */ | ||
856 | if (res_check(fh, RESOURCE_OVERLAY)) { | ||
857 | /* FIXME */ | ||
858 | res_free(dev,fh,RESOURCE_OVERLAY); | ||
859 | } | ||
860 | |||
861 | /* stop video capture */ | ||
862 | if (res_check(fh, RESOURCE_VIDEO)) { | ||
863 | videobuf_queue_cancel(&fh->vidq); | ||
864 | res_free(dev,fh,RESOURCE_VIDEO); | ||
865 | } | 619 | } |
866 | if (fh->vidq.read_buf) { | 620 | call_all(core, tuner, s_radio); |
867 | buffer_release(&fh->vidq,fh->vidq.read_buf); | ||
868 | kfree(fh->vidq.read_buf); | ||
869 | } | ||
870 | |||
871 | /* stop vbi capture */ | ||
872 | if (res_check(fh, RESOURCE_VBI)) { | ||
873 | videobuf_stop(&fh->vbiq); | ||
874 | res_free(dev,fh,RESOURCE_VBI); | ||
875 | } | ||
876 | |||
877 | videobuf_mmap_free(&fh->vidq); | ||
878 | videobuf_mmap_free(&fh->vbiq); | ||
879 | |||
880 | mutex_lock(&dev->core->lock); | ||
881 | v4l2_fh_del(&fh->fh); | ||
882 | v4l2_fh_exit(&fh->fh); | ||
883 | file->private_data = NULL; | ||
884 | kfree(fh); | ||
885 | |||
886 | dev->core->users--; | ||
887 | if (!dev->core->users) | ||
888 | call_all(dev->core, core, s_power, 0); | ||
889 | mutex_unlock(&dev->core->lock); | ||
890 | |||
891 | return 0; | 621 | return 0; |
892 | } | 622 | } |
893 | 623 | ||
894 | static int | ||
895 | video_mmap(struct file *file, struct vm_area_struct * vma) | ||
896 | { | ||
897 | return videobuf_mmap_mapper(get_queue(file), vma); | ||
898 | } | ||
899 | |||
900 | /* ------------------------------------------------------------------ */ | 624 | /* ------------------------------------------------------------------ */ |
901 | /* VIDEO CTRL IOCTLS */ | 625 | /* VIDEO CTRL IOCTLS */ |
902 | 626 | ||
@@ -999,12 +723,12 @@ static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl) | |||
999 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 723 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
1000 | struct v4l2_format *f) | 724 | struct v4l2_format *f) |
1001 | { | 725 | { |
1002 | struct cx8800_fh *fh = priv; | 726 | struct cx8800_dev *dev = video_drvdata(file); |
1003 | struct cx8800_dev *dev = fh->dev; | 727 | struct cx88_core *core = dev->core; |
1004 | 728 | ||
1005 | f->fmt.pix.width = dev->width; | 729 | f->fmt.pix.width = core->width; |
1006 | f->fmt.pix.height = dev->height; | 730 | f->fmt.pix.height = core->height; |
1007 | f->fmt.pix.field = fh->vidq.field; | 731 | f->fmt.pix.field = core->field; |
1008 | f->fmt.pix.pixelformat = dev->fmt->fourcc; | 732 | f->fmt.pix.pixelformat = dev->fmt->fourcc; |
1009 | f->fmt.pix.bytesperline = | 733 | f->fmt.pix.bytesperline = |
1010 | (f->fmt.pix.width * dev->fmt->depth) >> 3; | 734 | (f->fmt.pix.width * dev->fmt->depth) >> 3; |
@@ -1017,7 +741,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
1017 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 741 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
1018 | struct v4l2_format *f) | 742 | struct v4l2_format *f) |
1019 | { | 743 | { |
1020 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 744 | struct cx8800_dev *dev = video_drvdata(file); |
745 | struct cx88_core *core = dev->core; | ||
1021 | const struct cx8800_fmt *fmt; | 746 | const struct cx8800_fmt *fmt; |
1022 | enum v4l2_field field; | 747 | enum v4l2_field field; |
1023 | unsigned int maxw, maxh; | 748 | unsigned int maxw, maxh; |
@@ -1026,30 +751,30 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1026 | if (NULL == fmt) | 751 | if (NULL == fmt) |
1027 | return -EINVAL; | 752 | return -EINVAL; |
1028 | 753 | ||
1029 | field = f->fmt.pix.field; | 754 | maxw = norm_maxw(core->tvnorm); |
1030 | maxw = norm_maxw(core->tvnorm); | 755 | maxh = norm_maxh(core->tvnorm); |
1031 | maxh = norm_maxh(core->tvnorm); | ||
1032 | 756 | ||
1033 | if (V4L2_FIELD_ANY == field) { | 757 | field = f->fmt.pix.field; |
1034 | field = (f->fmt.pix.height > maxh/2) | ||
1035 | ? V4L2_FIELD_INTERLACED | ||
1036 | : V4L2_FIELD_BOTTOM; | ||
1037 | } | ||
1038 | 758 | ||
1039 | switch (field) { | 759 | switch (field) { |
1040 | case V4L2_FIELD_TOP: | 760 | case V4L2_FIELD_TOP: |
1041 | case V4L2_FIELD_BOTTOM: | 761 | case V4L2_FIELD_BOTTOM: |
1042 | maxh = maxh / 2; | ||
1043 | break; | ||
1044 | case V4L2_FIELD_INTERLACED: | 762 | case V4L2_FIELD_INTERLACED: |
763 | case V4L2_FIELD_SEQ_BT: | ||
764 | case V4L2_FIELD_SEQ_TB: | ||
1045 | break; | 765 | break; |
1046 | default: | 766 | default: |
1047 | return -EINVAL; | 767 | field = (f->fmt.pix.height > maxh / 2) |
768 | ? V4L2_FIELD_INTERLACED | ||
769 | : V4L2_FIELD_BOTTOM; | ||
770 | break; | ||
1048 | } | 771 | } |
772 | if (V4L2_FIELD_HAS_T_OR_B(field)) | ||
773 | maxh /= 2; | ||
1049 | 774 | ||
1050 | f->fmt.pix.field = field; | ||
1051 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | 775 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, |
1052 | &f->fmt.pix.height, 32, maxh, 0, 0); | 776 | &f->fmt.pix.height, 32, maxh, 0, 0); |
777 | f->fmt.pix.field = field; | ||
1053 | f->fmt.pix.bytesperline = | 778 | f->fmt.pix.bytesperline = |
1054 | (f->fmt.pix.width * fmt->depth) >> 3; | 779 | (f->fmt.pix.width * fmt->depth) >> 3; |
1055 | f->fmt.pix.sizeimage = | 780 | f->fmt.pix.sizeimage = |
@@ -1061,16 +786,20 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1061 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 786 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
1062 | struct v4l2_format *f) | 787 | struct v4l2_format *f) |
1063 | { | 788 | { |
1064 | struct cx8800_fh *fh = priv; | 789 | struct cx8800_dev *dev = video_drvdata(file); |
1065 | struct cx8800_dev *dev = fh->dev; | 790 | struct cx88_core *core = dev->core; |
1066 | int err = vidioc_try_fmt_vid_cap (file,priv,f); | 791 | int err = vidioc_try_fmt_vid_cap (file,priv,f); |
1067 | 792 | ||
1068 | if (0 != err) | 793 | if (0 != err) |
1069 | return err; | 794 | return err; |
1070 | dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 795 | if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq)) |
1071 | dev->width = f->fmt.pix.width; | 796 | return -EBUSY; |
1072 | dev->height = f->fmt.pix.height; | 797 | if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq)) |
1073 | fh->vidq.field = f->fmt.pix.field; | 798 | return -EBUSY; |
799 | dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
800 | core->width = f->fmt.pix.width; | ||
801 | core->height = f->fmt.pix.height; | ||
802 | core->field = f->fmt.pix.field; | ||
1074 | return 0; | 803 | return 0; |
1075 | } | 804 | } |
1076 | 805 | ||
@@ -1104,8 +833,8 @@ EXPORT_SYMBOL(cx88_querycap); | |||
1104 | static int vidioc_querycap(struct file *file, void *priv, | 833 | static int vidioc_querycap(struct file *file, void *priv, |
1105 | struct v4l2_capability *cap) | 834 | struct v4l2_capability *cap) |
1106 | { | 835 | { |
1107 | struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; | 836 | struct cx8800_dev *dev = video_drvdata(file); |
1108 | struct cx88_core *core = dev->core; | 837 | struct cx88_core *core = dev->core; |
1109 | 838 | ||
1110 | strcpy(cap->driver, "cx8800"); | 839 | strcpy(cap->driver, "cx8800"); |
1111 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); | 840 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); |
@@ -1125,64 +854,10 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | |||
1125 | return 0; | 854 | return 0; |
1126 | } | 855 | } |
1127 | 856 | ||
1128 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) | ||
1129 | { | ||
1130 | return videobuf_reqbufs(get_queue(file), p); | ||
1131 | } | ||
1132 | |||
1133 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1134 | { | ||
1135 | return videobuf_querybuf(get_queue(file), p); | ||
1136 | } | ||
1137 | |||
1138 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1139 | { | ||
1140 | return videobuf_qbuf(get_queue(file), p); | ||
1141 | } | ||
1142 | |||
1143 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1144 | { | ||
1145 | return videobuf_dqbuf(get_queue(file), p, | ||
1146 | file->f_flags & O_NONBLOCK); | ||
1147 | } | ||
1148 | |||
1149 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1150 | { | ||
1151 | struct video_device *vdev = video_devdata(file); | ||
1152 | struct cx8800_fh *fh = priv; | ||
1153 | struct cx8800_dev *dev = fh->dev; | ||
1154 | |||
1155 | if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
1156 | (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
1157 | return -EINVAL; | ||
1158 | |||
1159 | if (unlikely(!res_get(dev, fh, get_resource(file)))) | ||
1160 | return -EBUSY; | ||
1161 | return videobuf_streamon(get_queue(file)); | ||
1162 | } | ||
1163 | |||
1164 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1165 | { | ||
1166 | struct video_device *vdev = video_devdata(file); | ||
1167 | struct cx8800_fh *fh = priv; | ||
1168 | struct cx8800_dev *dev = fh->dev; | ||
1169 | int err, res; | ||
1170 | |||
1171 | if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
1172 | (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
1173 | return -EINVAL; | ||
1174 | |||
1175 | res = get_resource(file); | ||
1176 | err = videobuf_streamoff(get_queue(file)); | ||
1177 | if (err < 0) | ||
1178 | return err; | ||
1179 | res_free(dev,fh,res); | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | 857 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) |
1184 | { | 858 | { |
1185 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 859 | struct cx8800_dev *dev = video_drvdata(file); |
860 | struct cx88_core *core = dev->core; | ||
1186 | 861 | ||
1187 | *tvnorm = core->tvnorm; | 862 | *tvnorm = core->tvnorm; |
1188 | return 0; | 863 | return 0; |
@@ -1190,13 +865,10 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | |||
1190 | 865 | ||
1191 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms) | 866 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms) |
1192 | { | 867 | { |
1193 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 868 | struct cx8800_dev *dev = video_drvdata(file); |
1194 | 869 | struct cx88_core *core = dev->core; | |
1195 | mutex_lock(&core->lock); | ||
1196 | cx88_set_tvnorm(core, tvnorms); | ||
1197 | mutex_unlock(&core->lock); | ||
1198 | 870 | ||
1199 | return 0; | 871 | return cx88_set_tvnorm(core, tvnorms); |
1200 | } | 872 | } |
1201 | 873 | ||
1202 | /* only one input in this sample driver */ | 874 | /* only one input in this sample driver */ |
@@ -1233,13 +905,15 @@ EXPORT_SYMBOL(cx88_enum_input); | |||
1233 | static int vidioc_enum_input (struct file *file, void *priv, | 905 | static int vidioc_enum_input (struct file *file, void *priv, |
1234 | struct v4l2_input *i) | 906 | struct v4l2_input *i) |
1235 | { | 907 | { |
1236 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 908 | struct cx8800_dev *dev = video_drvdata(file); |
909 | struct cx88_core *core = dev->core; | ||
1237 | return cx88_enum_input (core,i); | 910 | return cx88_enum_input (core,i); |
1238 | } | 911 | } |
1239 | 912 | ||
1240 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | 913 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
1241 | { | 914 | { |
1242 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 915 | struct cx8800_dev *dev = video_drvdata(file); |
916 | struct cx88_core *core = dev->core; | ||
1243 | 917 | ||
1244 | *i = core->input; | 918 | *i = core->input; |
1245 | return 0; | 919 | return 0; |
@@ -1247,24 +921,24 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | |||
1247 | 921 | ||
1248 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | 922 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
1249 | { | 923 | { |
1250 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 924 | struct cx8800_dev *dev = video_drvdata(file); |
925 | struct cx88_core *core = dev->core; | ||
1251 | 926 | ||
1252 | if (i >= 4) | 927 | if (i >= 4) |
1253 | return -EINVAL; | 928 | return -EINVAL; |
1254 | if (0 == INPUT(i).type) | 929 | if (0 == INPUT(i).type) |
1255 | return -EINVAL; | 930 | return -EINVAL; |
1256 | 931 | ||
1257 | mutex_lock(&core->lock); | ||
1258 | cx88_newstation(core); | 932 | cx88_newstation(core); |
1259 | cx88_video_mux(core,i); | 933 | cx88_video_mux(core,i); |
1260 | mutex_unlock(&core->lock); | ||
1261 | return 0; | 934 | return 0; |
1262 | } | 935 | } |
1263 | 936 | ||
1264 | static int vidioc_g_tuner (struct file *file, void *priv, | 937 | static int vidioc_g_tuner (struct file *file, void *priv, |
1265 | struct v4l2_tuner *t) | 938 | struct v4l2_tuner *t) |
1266 | { | 939 | { |
1267 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 940 | struct cx8800_dev *dev = video_drvdata(file); |
941 | struct cx88_core *core = dev->core; | ||
1268 | u32 reg; | 942 | u32 reg; |
1269 | 943 | ||
1270 | if (unlikely(UNSET == core->board.tuner_type)) | 944 | if (unlikely(UNSET == core->board.tuner_type)) |
@@ -1286,7 +960,8 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
1286 | static int vidioc_s_tuner (struct file *file, void *priv, | 960 | static int vidioc_s_tuner (struct file *file, void *priv, |
1287 | const struct v4l2_tuner *t) | 961 | const struct v4l2_tuner *t) |
1288 | { | 962 | { |
1289 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 963 | struct cx8800_dev *dev = video_drvdata(file); |
964 | struct cx88_core *core = dev->core; | ||
1290 | 965 | ||
1291 | if (UNSET == core->board.tuner_type) | 966 | if (UNSET == core->board.tuner_type) |
1292 | return -EINVAL; | 967 | return -EINVAL; |
@@ -1300,8 +975,8 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
1300 | static int vidioc_g_frequency (struct file *file, void *priv, | 975 | static int vidioc_g_frequency (struct file *file, void *priv, |
1301 | struct v4l2_frequency *f) | 976 | struct v4l2_frequency *f) |
1302 | { | 977 | { |
1303 | struct cx8800_fh *fh = priv; | 978 | struct cx8800_dev *dev = video_drvdata(file); |
1304 | struct cx88_core *core = fh->dev->core; | 979 | struct cx88_core *core = dev->core; |
1305 | 980 | ||
1306 | if (unlikely(UNSET == core->board.tuner_type)) | 981 | if (unlikely(UNSET == core->board.tuner_type)) |
1307 | return -EINVAL; | 982 | return -EINVAL; |
@@ -1325,7 +1000,6 @@ int cx88_set_freq (struct cx88_core *core, | |||
1325 | if (unlikely(f->tuner != 0)) | 1000 | if (unlikely(f->tuner != 0)) |
1326 | return -EINVAL; | 1001 | return -EINVAL; |
1327 | 1002 | ||
1328 | mutex_lock(&core->lock); | ||
1329 | cx88_newstation(core); | 1003 | cx88_newstation(core); |
1330 | call_all(core, tuner, s_frequency, f); | 1004 | call_all(core, tuner, s_frequency, f); |
1331 | call_all(core, tuner, g_frequency, &new_freq); | 1005 | call_all(core, tuner, g_frequency, &new_freq); |
@@ -1335,8 +1009,6 @@ int cx88_set_freq (struct cx88_core *core, | |||
1335 | msleep (10); | 1009 | msleep (10); |
1336 | cx88_set_tvaudio(core); | 1010 | cx88_set_tvaudio(core); |
1337 | 1011 | ||
1338 | mutex_unlock(&core->lock); | ||
1339 | |||
1340 | return 0; | 1012 | return 0; |
1341 | } | 1013 | } |
1342 | EXPORT_SYMBOL(cx88_set_freq); | 1014 | EXPORT_SYMBOL(cx88_set_freq); |
@@ -1344,8 +1016,8 @@ EXPORT_SYMBOL(cx88_set_freq); | |||
1344 | static int vidioc_s_frequency (struct file *file, void *priv, | 1016 | static int vidioc_s_frequency (struct file *file, void *priv, |
1345 | const struct v4l2_frequency *f) | 1017 | const struct v4l2_frequency *f) |
1346 | { | 1018 | { |
1347 | struct cx8800_fh *fh = priv; | 1019 | struct cx8800_dev *dev = video_drvdata(file); |
1348 | struct cx88_core *core = fh->dev->core; | 1020 | struct cx88_core *core = dev->core; |
1349 | 1021 | ||
1350 | return cx88_set_freq(core, f); | 1022 | return cx88_set_freq(core, f); |
1351 | } | 1023 | } |
@@ -1354,7 +1026,8 @@ static int vidioc_s_frequency (struct file *file, void *priv, | |||
1354 | static int vidioc_g_register (struct file *file, void *fh, | 1026 | static int vidioc_g_register (struct file *file, void *fh, |
1355 | struct v4l2_dbg_register *reg) | 1027 | struct v4l2_dbg_register *reg) |
1356 | { | 1028 | { |
1357 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | 1029 | struct cx8800_dev *dev = video_drvdata(file); |
1030 | struct cx88_core *core = dev->core; | ||
1358 | 1031 | ||
1359 | /* cx2388x has a 24-bit register space */ | 1032 | /* cx2388x has a 24-bit register space */ |
1360 | reg->val = cx_read(reg->reg & 0xfffffc); | 1033 | reg->val = cx_read(reg->reg & 0xfffffc); |
@@ -1365,7 +1038,8 @@ static int vidioc_g_register (struct file *file, void *fh, | |||
1365 | static int vidioc_s_register (struct file *file, void *fh, | 1038 | static int vidioc_s_register (struct file *file, void *fh, |
1366 | const struct v4l2_dbg_register *reg) | 1039 | const struct v4l2_dbg_register *reg) |
1367 | { | 1040 | { |
1368 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | 1041 | struct cx8800_dev *dev = video_drvdata(file); |
1042 | struct cx88_core *core = dev->core; | ||
1369 | 1043 | ||
1370 | cx_write(reg->reg & 0xfffffc, reg->val); | 1044 | cx_write(reg->reg & 0xfffffc, reg->val); |
1371 | return 0; | 1045 | return 0; |
@@ -1379,7 +1053,8 @@ static int vidioc_s_register (struct file *file, void *fh, | |||
1379 | static int radio_g_tuner (struct file *file, void *priv, | 1053 | static int radio_g_tuner (struct file *file, void *priv, |
1380 | struct v4l2_tuner *t) | 1054 | struct v4l2_tuner *t) |
1381 | { | 1055 | { |
1382 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 1056 | struct cx8800_dev *dev = video_drvdata(file); |
1057 | struct cx88_core *core = dev->core; | ||
1383 | 1058 | ||
1384 | if (unlikely(t->index > 0)) | 1059 | if (unlikely(t->index > 0)) |
1385 | return -EINVAL; | 1060 | return -EINVAL; |
@@ -1393,7 +1068,8 @@ static int radio_g_tuner (struct file *file, void *priv, | |||
1393 | static int radio_s_tuner (struct file *file, void *priv, | 1068 | static int radio_s_tuner (struct file *file, void *priv, |
1394 | const struct v4l2_tuner *t) | 1069 | const struct v4l2_tuner *t) |
1395 | { | 1070 | { |
1396 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 1071 | struct cx8800_dev *dev = video_drvdata(file); |
1072 | struct cx88_core *core = dev->core; | ||
1397 | 1073 | ||
1398 | if (0 != t->index) | 1074 | if (0 != t->index) |
1399 | return -EINVAL; | 1075 | return -EINVAL; |
@@ -1404,32 +1080,6 @@ static int radio_s_tuner (struct file *file, void *priv, | |||
1404 | 1080 | ||
1405 | /* ----------------------------------------------------------- */ | 1081 | /* ----------------------------------------------------------- */ |
1406 | 1082 | ||
1407 | static void cx8800_vid_timeout(unsigned long data) | ||
1408 | { | ||
1409 | struct cx8800_dev *dev = (struct cx8800_dev*)data; | ||
1410 | struct cx88_core *core = dev->core; | ||
1411 | struct cx88_dmaqueue *q = &dev->vidq; | ||
1412 | struct cx88_buffer *buf; | ||
1413 | unsigned long flags; | ||
1414 | |||
1415 | cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]); | ||
1416 | |||
1417 | cx_clear(MO_VID_DMACNTRL, 0x11); | ||
1418 | cx_clear(VID_CAPTURE_CONTROL, 0x06); | ||
1419 | |||
1420 | spin_lock_irqsave(&dev->slock,flags); | ||
1421 | while (!list_empty(&q->active)) { | ||
1422 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | ||
1423 | list_del(&buf->vb.queue); | ||
1424 | buf->vb.state = VIDEOBUF_ERROR; | ||
1425 | wake_up(&buf->vb.done); | ||
1426 | printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name, | ||
1427 | buf, buf->vb.i, (unsigned long)buf->risc.dma); | ||
1428 | } | ||
1429 | restart_video_queue(dev,q); | ||
1430 | spin_unlock_irqrestore(&dev->slock,flags); | ||
1431 | } | ||
1432 | |||
1433 | static const char *cx88_vid_irqs[32] = { | 1083 | static const char *cx88_vid_irqs[32] = { |
1434 | "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", | 1084 | "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", |
1435 | "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", | 1085 | "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", |
@@ -1476,22 +1126,6 @@ static void cx8800_vid_irq(struct cx8800_dev *dev) | |||
1476 | cx88_wakeup(core, &dev->vbiq, count); | 1126 | cx88_wakeup(core, &dev->vbiq, count); |
1477 | spin_unlock(&dev->slock); | 1127 | spin_unlock(&dev->slock); |
1478 | } | 1128 | } |
1479 | |||
1480 | /* risc2 y */ | ||
1481 | if (status & 0x10) { | ||
1482 | dprintk(2,"stopper video\n"); | ||
1483 | spin_lock(&dev->slock); | ||
1484 | restart_video_queue(dev,&dev->vidq); | ||
1485 | spin_unlock(&dev->slock); | ||
1486 | } | ||
1487 | |||
1488 | /* risc2 vbi */ | ||
1489 | if (status & 0x80) { | ||
1490 | dprintk(2,"stopper vbi\n"); | ||
1491 | spin_lock(&dev->slock); | ||
1492 | cx8800_restart_vbi_queue(dev,&dev->vbiq); | ||
1493 | spin_unlock(&dev->slock); | ||
1494 | } | ||
1495 | } | 1129 | } |
1496 | 1130 | ||
1497 | static irqreturn_t cx8800_irq(int irq, void *dev_id) | 1131 | static irqreturn_t cx8800_irq(int irq, void *dev_id) |
@@ -1530,11 +1164,11 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) | |||
1530 | static const struct v4l2_file_operations video_fops = | 1164 | static const struct v4l2_file_operations video_fops = |
1531 | { | 1165 | { |
1532 | .owner = THIS_MODULE, | 1166 | .owner = THIS_MODULE, |
1533 | .open = video_open, | 1167 | .open = v4l2_fh_open, |
1534 | .release = video_release, | 1168 | .release = vb2_fop_release, |
1535 | .read = video_read, | 1169 | .read = vb2_fop_read, |
1536 | .poll = video_poll, | 1170 | .poll = vb2_fop_poll, |
1537 | .mmap = video_mmap, | 1171 | .mmap = vb2_fop_mmap, |
1538 | .unlocked_ioctl = video_ioctl2, | 1172 | .unlocked_ioctl = video_ioctl2, |
1539 | }; | 1173 | }; |
1540 | 1174 | ||
@@ -1544,17 +1178,17 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1544 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1178 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1545 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 1179 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1546 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1180 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1547 | .vidioc_reqbufs = vidioc_reqbufs, | 1181 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1548 | .vidioc_querybuf = vidioc_querybuf, | 1182 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1549 | .vidioc_qbuf = vidioc_qbuf, | 1183 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1550 | .vidioc_dqbuf = vidioc_dqbuf, | 1184 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1551 | .vidioc_g_std = vidioc_g_std, | 1185 | .vidioc_g_std = vidioc_g_std, |
1552 | .vidioc_s_std = vidioc_s_std, | 1186 | .vidioc_s_std = vidioc_s_std, |
1553 | .vidioc_enum_input = vidioc_enum_input, | 1187 | .vidioc_enum_input = vidioc_enum_input, |
1554 | .vidioc_g_input = vidioc_g_input, | 1188 | .vidioc_g_input = vidioc_g_input, |
1555 | .vidioc_s_input = vidioc_s_input, | 1189 | .vidioc_s_input = vidioc_s_input, |
1556 | .vidioc_streamon = vidioc_streamon, | 1190 | .vidioc_streamon = vb2_ioctl_streamon, |
1557 | .vidioc_streamoff = vidioc_streamoff, | 1191 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1558 | .vidioc_g_tuner = vidioc_g_tuner, | 1192 | .vidioc_g_tuner = vidioc_g_tuner, |
1559 | .vidioc_s_tuner = vidioc_s_tuner, | 1193 | .vidioc_s_tuner = vidioc_s_tuner, |
1560 | .vidioc_g_frequency = vidioc_g_frequency, | 1194 | .vidioc_g_frequency = vidioc_g_frequency, |
@@ -1579,17 +1213,17 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { | |||
1579 | .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, | 1213 | .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, |
1580 | .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, | 1214 | .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, |
1581 | .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, | 1215 | .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, |
1582 | .vidioc_reqbufs = vidioc_reqbufs, | 1216 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1583 | .vidioc_querybuf = vidioc_querybuf, | 1217 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1584 | .vidioc_qbuf = vidioc_qbuf, | 1218 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1585 | .vidioc_dqbuf = vidioc_dqbuf, | 1219 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1586 | .vidioc_g_std = vidioc_g_std, | 1220 | .vidioc_g_std = vidioc_g_std, |
1587 | .vidioc_s_std = vidioc_s_std, | 1221 | .vidioc_s_std = vidioc_s_std, |
1588 | .vidioc_enum_input = vidioc_enum_input, | 1222 | .vidioc_enum_input = vidioc_enum_input, |
1589 | .vidioc_g_input = vidioc_g_input, | 1223 | .vidioc_g_input = vidioc_g_input, |
1590 | .vidioc_s_input = vidioc_s_input, | 1224 | .vidioc_s_input = vidioc_s_input, |
1591 | .vidioc_streamon = vidioc_streamon, | 1225 | .vidioc_streamon = vb2_ioctl_streamon, |
1592 | .vidioc_streamoff = vidioc_streamoff, | 1226 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1593 | .vidioc_g_tuner = vidioc_g_tuner, | 1227 | .vidioc_g_tuner = vidioc_g_tuner, |
1594 | .vidioc_s_tuner = vidioc_s_tuner, | 1228 | .vidioc_s_tuner = vidioc_s_tuner, |
1595 | .vidioc_g_frequency = vidioc_g_frequency, | 1229 | .vidioc_g_frequency = vidioc_g_frequency, |
@@ -1610,9 +1244,9 @@ static const struct video_device cx8800_vbi_template = { | |||
1610 | static const struct v4l2_file_operations radio_fops = | 1244 | static const struct v4l2_file_operations radio_fops = |
1611 | { | 1245 | { |
1612 | .owner = THIS_MODULE, | 1246 | .owner = THIS_MODULE, |
1613 | .open = video_open, | 1247 | .open = radio_open, |
1614 | .poll = v4l2_ctrl_poll, | 1248 | .poll = v4l2_ctrl_poll, |
1615 | .release = video_release, | 1249 | .release = v4l2_fh_release, |
1616 | .unlocked_ioctl = video_ioctl2, | 1250 | .unlocked_ioctl = video_ioctl2, |
1617 | }; | 1251 | }; |
1618 | 1252 | ||
@@ -1676,6 +1310,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1676 | { | 1310 | { |
1677 | struct cx8800_dev *dev; | 1311 | struct cx8800_dev *dev; |
1678 | struct cx88_core *core; | 1312 | struct cx88_core *core; |
1313 | struct vb2_queue *q; | ||
1679 | int err; | 1314 | int err; |
1680 | int i; | 1315 | int i; |
1681 | 1316 | ||
@@ -1713,25 +1348,12 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1713 | 1348 | ||
1714 | /* initialize driver struct */ | 1349 | /* initialize driver struct */ |
1715 | spin_lock_init(&dev->slock); | 1350 | spin_lock_init(&dev->slock); |
1716 | core->tvnorm = V4L2_STD_NTSC_M; | ||
1717 | 1351 | ||
1718 | /* init video dma queues */ | 1352 | /* init video dma queues */ |
1719 | INIT_LIST_HEAD(&dev->vidq.active); | 1353 | INIT_LIST_HEAD(&dev->vidq.active); |
1720 | INIT_LIST_HEAD(&dev->vidq.queued); | ||
1721 | dev->vidq.timeout.function = cx8800_vid_timeout; | ||
1722 | dev->vidq.timeout.data = (unsigned long)dev; | ||
1723 | init_timer(&dev->vidq.timeout); | ||
1724 | cx88_risc_stopper(dev->pci,&dev->vidq.stopper, | ||
1725 | MO_VID_DMACNTRL,0x11,0x00); | ||
1726 | 1354 | ||
1727 | /* init vbi dma queues */ | 1355 | /* init vbi dma queues */ |
1728 | INIT_LIST_HEAD(&dev->vbiq.active); | 1356 | INIT_LIST_HEAD(&dev->vbiq.active); |
1729 | INIT_LIST_HEAD(&dev->vbiq.queued); | ||
1730 | dev->vbiq.timeout.function = cx8800_vbi_timeout; | ||
1731 | dev->vbiq.timeout.data = (unsigned long)dev; | ||
1732 | init_timer(&dev->vbiq.timeout); | ||
1733 | cx88_risc_stopper(dev->pci,&dev->vbiq.stopper, | ||
1734 | MO_VID_DMACNTRL,0x88,0x00); | ||
1735 | 1357 | ||
1736 | /* get irq */ | 1358 | /* get irq */ |
1737 | err = request_irq(pci_dev->irq, cx8800_irq, | 1359 | err = request_irq(pci_dev->irq, cx8800_irq, |
@@ -1820,9 +1442,10 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1820 | /* Sets device info at pci_dev */ | 1442 | /* Sets device info at pci_dev */ |
1821 | pci_set_drvdata(pci_dev, dev); | 1443 | pci_set_drvdata(pci_dev, dev); |
1822 | 1444 | ||
1823 | dev->width = 320; | 1445 | dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); |
1824 | dev->height = 240; | 1446 | |
1825 | dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); | 1447 | /* Maintain a reference so cx88-blackbird can query the 8800 device. */ |
1448 | core->v4ldev = dev; | ||
1826 | 1449 | ||
1827 | /* initial device configuration */ | 1450 | /* initial device configuration */ |
1828 | mutex_lock(&core->lock); | 1451 | mutex_lock(&core->lock); |
@@ -1831,11 +1454,44 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1831 | v4l2_ctrl_handler_setup(&core->audio_hdl); | 1454 | v4l2_ctrl_handler_setup(&core->audio_hdl); |
1832 | cx88_video_mux(core, 0); | 1455 | cx88_video_mux(core, 0); |
1833 | 1456 | ||
1457 | q = &dev->vb2_vidq; | ||
1458 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1459 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||
1460 | q->gfp_flags = GFP_DMA32; | ||
1461 | q->min_buffers_needed = 2; | ||
1462 | q->drv_priv = dev; | ||
1463 | q->buf_struct_size = sizeof(struct cx88_buffer); | ||
1464 | q->ops = &cx8800_video_qops; | ||
1465 | q->mem_ops = &vb2_dma_sg_memops; | ||
1466 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1467 | q->lock = &core->lock; | ||
1468 | |||
1469 | err = vb2_queue_init(q); | ||
1470 | if (err < 0) | ||
1471 | goto fail_unreg; | ||
1472 | |||
1473 | q = &dev->vb2_vbiq; | ||
1474 | q->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1475 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||
1476 | q->gfp_flags = GFP_DMA32; | ||
1477 | q->min_buffers_needed = 2; | ||
1478 | q->drv_priv = dev; | ||
1479 | q->buf_struct_size = sizeof(struct cx88_buffer); | ||
1480 | q->ops = &cx8800_vbi_qops; | ||
1481 | q->mem_ops = &vb2_dma_sg_memops; | ||
1482 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1483 | q->lock = &core->lock; | ||
1484 | |||
1485 | err = vb2_queue_init(q); | ||
1486 | if (err < 0) | ||
1487 | goto fail_unreg; | ||
1488 | |||
1834 | /* register v4l devices */ | 1489 | /* register v4l devices */ |
1835 | dev->video_dev = cx88_vdev_init(core,dev->pci, | 1490 | dev->video_dev = cx88_vdev_init(core,dev->pci, |
1836 | &cx8800_video_template,"video"); | 1491 | &cx8800_video_template,"video"); |
1837 | video_set_drvdata(dev->video_dev, dev); | 1492 | video_set_drvdata(dev->video_dev, dev); |
1838 | dev->video_dev->ctrl_handler = &core->video_hdl; | 1493 | dev->video_dev->ctrl_handler = &core->video_hdl; |
1494 | dev->video_dev->queue = &dev->vb2_vidq; | ||
1839 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, | 1495 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, |
1840 | video_nr[core->nr]); | 1496 | video_nr[core->nr]); |
1841 | if (err < 0) { | 1497 | if (err < 0) { |
@@ -1848,6 +1504,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1848 | 1504 | ||
1849 | dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); | 1505 | dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); |
1850 | video_set_drvdata(dev->vbi_dev, dev); | 1506 | video_set_drvdata(dev->vbi_dev, dev); |
1507 | dev->vbi_dev->queue = &dev->vb2_vbiq; | ||
1851 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, | 1508 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, |
1852 | vbi_nr[core->nr]); | 1509 | vbi_nr[core->nr]); |
1853 | if (err < 0) { | 1510 | if (err < 0) { |
@@ -1875,7 +1532,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1875 | } | 1532 | } |
1876 | 1533 | ||
1877 | /* start tvaudio thread */ | 1534 | /* start tvaudio thread */ |
1878 | if (core->board.tuner_type != TUNER_ABSENT) { | 1535 | if (core->board.tuner_type != UNSET) { |
1879 | core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); | 1536 | core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); |
1880 | if (IS_ERR(core->kthread)) { | 1537 | if (IS_ERR(core->kthread)) { |
1881 | err = PTR_ERR(core->kthread); | 1538 | err = PTR_ERR(core->kthread); |
@@ -1892,6 +1549,7 @@ fail_unreg: | |||
1892 | free_irq(pci_dev->irq, dev); | 1549 | free_irq(pci_dev->irq, dev); |
1893 | mutex_unlock(&core->lock); | 1550 | mutex_unlock(&core->lock); |
1894 | fail_core: | 1551 | fail_core: |
1552 | core->v4ldev = NULL; | ||
1895 | cx88_core_put(core,dev->pci); | 1553 | cx88_core_put(core,dev->pci); |
1896 | fail_free: | 1554 | fail_free: |
1897 | kfree(dev); | 1555 | kfree(dev); |
@@ -1913,15 +1571,16 @@ static void cx8800_finidev(struct pci_dev *pci_dev) | |||
1913 | cx88_ir_stop(core); | 1571 | cx88_ir_stop(core); |
1914 | 1572 | ||
1915 | cx88_shutdown(core); /* FIXME */ | 1573 | cx88_shutdown(core); /* FIXME */ |
1916 | pci_disable_device(pci_dev); | ||
1917 | 1574 | ||
1918 | /* unregister stuff */ | 1575 | /* unregister stuff */ |
1919 | 1576 | ||
1920 | free_irq(pci_dev->irq, dev); | 1577 | free_irq(pci_dev->irq, dev); |
1921 | cx8800_unregister_video(dev); | 1578 | cx8800_unregister_video(dev); |
1579 | pci_disable_device(pci_dev); | ||
1580 | |||
1581 | core->v4ldev = NULL; | ||
1922 | 1582 | ||
1923 | /* free memory */ | 1583 | /* free memory */ |
1924 | btcx_riscmem_free(dev->pci,&dev->vidq.stopper); | ||
1925 | cx88_core_put(core,dev->pci); | 1584 | cx88_core_put(core,dev->pci); |
1926 | kfree(dev); | 1585 | kfree(dev); |
1927 | } | 1586 | } |
@@ -1938,12 +1597,10 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
1938 | if (!list_empty(&dev->vidq.active)) { | 1597 | if (!list_empty(&dev->vidq.active)) { |
1939 | printk("%s/0: suspend video\n", core->name); | 1598 | printk("%s/0: suspend video\n", core->name); |
1940 | stop_video_dma(dev); | 1599 | stop_video_dma(dev); |
1941 | del_timer(&dev->vidq.timeout); | ||
1942 | } | 1600 | } |
1943 | if (!list_empty(&dev->vbiq.active)) { | 1601 | if (!list_empty(&dev->vbiq.active)) { |
1944 | printk("%s/0: suspend vbi\n", core->name); | 1602 | printk("%s/0: suspend vbi\n", core->name); |
1945 | cx8800_stop_vbi_dma(dev); | 1603 | cx8800_stop_vbi_dma(dev); |
1946 | del_timer(&dev->vbiq.timeout); | ||
1947 | } | 1604 | } |
1948 | spin_unlock_irqrestore(&dev->slock, flags); | 1605 | spin_unlock_irqrestore(&dev->slock, flags); |
1949 | 1606 | ||
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h index 28893a6b249e..3b0ae754f165 100644 --- a/drivers/media/pci/cx88/cx88.h +++ b/drivers/media/pci/cx88/cx88.h | |||
@@ -29,19 +29,18 @@ | |||
29 | #include <media/v4l2-fh.h> | 29 | #include <media/v4l2-fh.h> |
30 | #include <media/tuner.h> | 30 | #include <media/tuner.h> |
31 | #include <media/tveeprom.h> | 31 | #include <media/tveeprom.h> |
32 | #include <media/videobuf-dma-sg.h> | 32 | #include <media/videobuf2-dma-sg.h> |
33 | #include <media/cx2341x.h> | 33 | #include <media/cx2341x.h> |
34 | #include <media/videobuf-dvb.h> | 34 | #include <media/videobuf2-dvb.h> |
35 | #include <media/ir-kbd-i2c.h> | 35 | #include <media/ir-kbd-i2c.h> |
36 | #include <media/wm8775.h> | 36 | #include <media/wm8775.h> |
37 | 37 | ||
38 | #include "btcx-risc.h" | ||
39 | #include "cx88-reg.h" | 38 | #include "cx88-reg.h" |
40 | #include "tuner-xc2028.h" | 39 | #include "tuner-xc2028.h" |
41 | 40 | ||
42 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
43 | 42 | ||
44 | #define CX88_VERSION "0.0.9" | 43 | #define CX88_VERSION "1.0.0" |
45 | 44 | ||
46 | #define UNSET (-1U) | 45 | #define UNSET (-1U) |
47 | 46 | ||
@@ -62,7 +61,8 @@ | |||
62 | #define FORMAT_FLAGS_PACKED 0x01 | 61 | #define FORMAT_FLAGS_PACKED 0x01 |
63 | #define FORMAT_FLAGS_PLANAR 0x02 | 62 | #define FORMAT_FLAGS_PLANAR 0x02 |
64 | 63 | ||
65 | #define VBI_LINE_COUNT 17 | 64 | #define VBI_LINE_PAL_COUNT 18 |
65 | #define VBI_LINE_NTSC_COUNT 12 | ||
66 | #define VBI_LINE_LENGTH 2048 | 66 | #define VBI_LINE_LENGTH 2048 |
67 | 67 | ||
68 | #define AUD_RDS_LINES 4 | 68 | #define AUD_RDS_LINES 4 |
@@ -95,13 +95,13 @@ enum cx8802_board_access { | |||
95 | 95 | ||
96 | static inline unsigned int norm_maxw(v4l2_std_id norm) | 96 | static inline unsigned int norm_maxw(v4l2_std_id norm) |
97 | { | 97 | { |
98 | return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768; | 98 | return 720; |
99 | } | 99 | } |
100 | 100 | ||
101 | 101 | ||
102 | static inline unsigned int norm_maxh(v4l2_std_id norm) | 102 | static inline unsigned int norm_maxh(v4l2_std_id norm) |
103 | { | 103 | { |
104 | return (norm & V4L2_STD_625_50) ? 576 : 480; | 104 | return (norm & V4L2_STD_525_60) ? 480 : 576; |
105 | } | 105 | } |
106 | 106 | ||
107 | /* ----------------------------------------------------------- */ | 107 | /* ----------------------------------------------------------- */ |
@@ -311,26 +311,33 @@ enum cx88_tvaudio { | |||
311 | 311 | ||
312 | #define BUFFER_TIMEOUT msecs_to_jiffies(2000) | 312 | #define BUFFER_TIMEOUT msecs_to_jiffies(2000) |
313 | 313 | ||
314 | struct cx88_riscmem { | ||
315 | unsigned int size; | ||
316 | __le32 *cpu; | ||
317 | __le32 *jmp; | ||
318 | dma_addr_t dma; | ||
319 | }; | ||
320 | |||
314 | /* buffer for one video frame */ | 321 | /* buffer for one video frame */ |
315 | struct cx88_buffer { | 322 | struct cx88_buffer { |
316 | /* common v4l buffer stuff -- must be first */ | 323 | /* common v4l buffer stuff -- must be first */ |
317 | struct videobuf_buffer vb; | 324 | struct vb2_buffer vb; |
325 | struct list_head list; | ||
318 | 326 | ||
319 | /* cx88 specific */ | 327 | /* cx88 specific */ |
320 | unsigned int bpl; | 328 | unsigned int bpl; |
321 | struct btcx_riscmem risc; | 329 | struct cx88_riscmem risc; |
322 | const struct cx8800_fmt *fmt; | ||
323 | u32 count; | 330 | u32 count; |
324 | }; | 331 | }; |
325 | 332 | ||
326 | struct cx88_dmaqueue { | 333 | struct cx88_dmaqueue { |
327 | struct list_head active; | 334 | struct list_head active; |
328 | struct list_head queued; | ||
329 | struct timer_list timeout; | ||
330 | struct btcx_riscmem stopper; | ||
331 | u32 count; | 335 | u32 count; |
332 | }; | 336 | }; |
333 | 337 | ||
338 | struct cx8800_dev; | ||
339 | struct cx8802_dev; | ||
340 | |||
334 | struct cx88_core { | 341 | struct cx88_core { |
335 | struct list_head devlist; | 342 | struct list_head devlist; |
336 | atomic_t refcount; | 343 | atomic_t refcount; |
@@ -376,6 +383,8 @@ struct cx88_core { | |||
376 | /* state info */ | 383 | /* state info */ |
377 | struct task_struct *kthread; | 384 | struct task_struct *kthread; |
378 | v4l2_std_id tvnorm; | 385 | v4l2_std_id tvnorm; |
386 | unsigned width, height; | ||
387 | unsigned field; | ||
379 | enum cx88_tvaudio tvaudio; | 388 | enum cx88_tvaudio tvaudio; |
380 | u32 audiomode_manual; | 389 | u32 audiomode_manual; |
381 | u32 audiomode_current; | 390 | u32 audiomode_current; |
@@ -395,11 +404,14 @@ struct cx88_core { | |||
395 | struct mutex lock; | 404 | struct mutex lock; |
396 | /* various v4l controls */ | 405 | /* various v4l controls */ |
397 | u32 freq; | 406 | u32 freq; |
398 | int users; | ||
399 | int mpeg_users; | ||
400 | 407 | ||
401 | /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ | 408 | /* |
409 | * cx88-video needs to access cx8802 for hybrid tuner pll access and | ||
410 | * for vb2_is_busy() checks. | ||
411 | */ | ||
402 | struct cx8802_dev *dvbdev; | 412 | struct cx8802_dev *dvbdev; |
413 | /* cx88-blackbird needs to access cx8800 for vb2_is_busy() checks */ | ||
414 | struct cx8800_dev *v4ldev; | ||
403 | enum cx88_board_type active_type_id; | 415 | enum cx88_board_type active_type_id; |
404 | int active_ref; | 416 | int active_ref; |
405 | int active_fe_id; | 417 | int active_fe_id; |
@@ -453,24 +465,9 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev) | |||
453 | val; \ | 465 | val; \ |
454 | }) | 466 | }) |
455 | 467 | ||
456 | struct cx8800_dev; | ||
457 | struct cx8802_dev; | ||
458 | |||
459 | /* ----------------------------------------------------------- */ | 468 | /* ----------------------------------------------------------- */ |
460 | /* function 0: video stuff */ | 469 | /* function 0: video stuff */ |
461 | 470 | ||
462 | struct cx8800_fh { | ||
463 | struct v4l2_fh fh; | ||
464 | struct cx8800_dev *dev; | ||
465 | unsigned int resources; | ||
466 | |||
467 | /* video capture */ | ||
468 | struct videobuf_queue vidq; | ||
469 | |||
470 | /* vbi capture */ | ||
471 | struct videobuf_queue vbiq; | ||
472 | }; | ||
473 | |||
474 | struct cx8800_suspend_state { | 471 | struct cx8800_suspend_state { |
475 | int disabled; | 472 | int disabled; |
476 | }; | 473 | }; |
@@ -490,11 +487,12 @@ struct cx8800_dev { | |||
490 | unsigned char pci_rev,pci_lat; | 487 | unsigned char pci_rev,pci_lat; |
491 | 488 | ||
492 | const struct cx8800_fmt *fmt; | 489 | const struct cx8800_fmt *fmt; |
493 | unsigned int width, height; | ||
494 | 490 | ||
495 | /* capture queues */ | 491 | /* capture queues */ |
496 | struct cx88_dmaqueue vidq; | 492 | struct cx88_dmaqueue vidq; |
493 | struct vb2_queue vb2_vidq; | ||
497 | struct cx88_dmaqueue vbiq; | 494 | struct cx88_dmaqueue vbiq; |
495 | struct vb2_queue vb2_vbiq; | ||
498 | 496 | ||
499 | /* various v4l controls */ | 497 | /* various v4l controls */ |
500 | 498 | ||
@@ -510,12 +508,6 @@ struct cx8800_dev { | |||
510 | /* ----------------------------------------------------------- */ | 508 | /* ----------------------------------------------------------- */ |
511 | /* function 2: mpeg stuff */ | 509 | /* function 2: mpeg stuff */ |
512 | 510 | ||
513 | struct cx8802_fh { | ||
514 | struct v4l2_fh fh; | ||
515 | struct cx8802_dev *dev; | ||
516 | struct videobuf_queue mpegq; | ||
517 | }; | ||
518 | |||
519 | struct cx8802_suspend_state { | 511 | struct cx8802_suspend_state { |
520 | int disabled; | 512 | int disabled; |
521 | }; | 513 | }; |
@@ -559,6 +551,7 @@ struct cx8802_dev { | |||
559 | 551 | ||
560 | /* dma queues */ | 552 | /* dma queues */ |
561 | struct cx88_dmaqueue mpegq; | 553 | struct cx88_dmaqueue mpegq; |
554 | struct vb2_queue vb2_mpegq; | ||
562 | u32 ts_packet_size; | 555 | u32 ts_packet_size; |
563 | u32 ts_packet_count; | 556 | u32 ts_packet_count; |
564 | 557 | ||
@@ -570,9 +563,6 @@ struct cx8802_dev { | |||
570 | #if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD) | 563 | #if IS_ENABLED(CONFIG_VIDEO_CX88_BLACKBIRD) |
571 | struct video_device *mpeg_dev; | 564 | struct video_device *mpeg_dev; |
572 | u32 mailbox; | 565 | u32 mailbox; |
573 | int width; | ||
574 | int height; | ||
575 | unsigned char mpeg_active; /* nonzero if mpeg encoder is active */ | ||
576 | 566 | ||
577 | /* mpeg params */ | 567 | /* mpeg params */ |
578 | struct cx2341x_handler cxhdl; | 568 | struct cx2341x_handler cxhdl; |
@@ -580,7 +570,7 @@ struct cx8802_dev { | |||
580 | 570 | ||
581 | #if IS_ENABLED(CONFIG_VIDEO_CX88_DVB) | 571 | #if IS_ENABLED(CONFIG_VIDEO_CX88_DVB) |
582 | /* for dvb only */ | 572 | /* for dvb only */ |
583 | struct videobuf_dvb_frontends frontends; | 573 | struct vb2_dvb_frontends frontends; |
584 | #endif | 574 | #endif |
585 | 575 | ||
586 | #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) | 576 | #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054) |
@@ -634,22 +624,17 @@ extern void cx88_shutdown(struct cx88_core *core); | |||
634 | extern int cx88_reset(struct cx88_core *core); | 624 | extern int cx88_reset(struct cx88_core *core); |
635 | 625 | ||
636 | extern int | 626 | extern int |
637 | cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 627 | cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc, |
638 | struct scatterlist *sglist, | 628 | struct scatterlist *sglist, |
639 | unsigned int top_offset, unsigned int bottom_offset, | 629 | unsigned int top_offset, unsigned int bottom_offset, |
640 | unsigned int bpl, unsigned int padding, unsigned int lines); | 630 | unsigned int bpl, unsigned int padding, unsigned int lines); |
641 | extern int | 631 | extern int |
642 | cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 632 | cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc, |
643 | struct scatterlist *sglist, unsigned int bpl, | 633 | struct scatterlist *sglist, unsigned int bpl, |
644 | unsigned int lines, unsigned int lpi); | 634 | unsigned int lines, unsigned int lpi); |
645 | extern int | ||
646 | cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | ||
647 | u32 reg, u32 mask, u32 value); | ||
648 | extern void | ||
649 | cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf); | ||
650 | 635 | ||
651 | extern void cx88_risc_disasm(struct cx88_core *core, | 636 | extern void cx88_risc_disasm(struct cx88_core *core, |
652 | struct btcx_riscmem *risc); | 637 | struct cx88_riscmem *risc); |
653 | extern int cx88_sram_channel_setup(struct cx88_core *core, | 638 | extern int cx88_sram_channel_setup(struct cx88_core *core, |
654 | const struct sram_channel *ch, | 639 | const struct sram_channel *ch, |
655 | unsigned int bpl, u32 risc); | 640 | unsigned int bpl, u32 risc); |
@@ -664,7 +649,7 @@ extern struct video_device *cx88_vdev_init(struct cx88_core *core, | |||
664 | struct pci_dev *pci, | 649 | struct pci_dev *pci, |
665 | const struct video_device *template_, | 650 | const struct video_device *template_, |
666 | const char *type); | 651 | const char *type); |
667 | extern struct cx88_core* cx88_core_get(struct pci_dev *pci); | 652 | extern struct cx88_core *cx88_core_get(struct pci_dev *pci); |
668 | extern void cx88_core_put(struct cx88_core *core, | 653 | extern void cx88_core_put(struct cx88_core *core, |
669 | struct pci_dev *pci); | 654 | struct pci_dev *pci); |
670 | 655 | ||
@@ -684,12 +669,10 @@ int cx8800_start_vbi_dma(struct cx8800_dev *dev, | |||
684 | struct cx88_dmaqueue *q, | 669 | struct cx88_dmaqueue *q, |
685 | struct cx88_buffer *buf); | 670 | struct cx88_buffer *buf); |
686 | */ | 671 | */ |
687 | int cx8800_stop_vbi_dma(struct cx8800_dev *dev); | 672 | void cx8800_stop_vbi_dma(struct cx8800_dev *dev); |
688 | int cx8800_restart_vbi_queue(struct cx8800_dev *dev, | 673 | int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q); |
689 | struct cx88_dmaqueue *q); | ||
690 | void cx8800_vbi_timeout(unsigned long data); | ||
691 | 674 | ||
692 | extern const struct videobuf_queue_ops cx8800_vbi_qops; | 675 | extern const struct vb2_ops cx8800_vbi_qops; |
693 | 676 | ||
694 | /* ----------------------------------------------------------- */ | 677 | /* ----------------------------------------------------------- */ |
695 | /* cx88-i2c.c */ | 678 | /* cx88-i2c.c */ |
@@ -739,14 +722,17 @@ extern void cx88_i2c_init_ir(struct cx88_core *core); | |||
739 | /* ----------------------------------------------------------- */ | 722 | /* ----------------------------------------------------------- */ |
740 | /* cx88-mpeg.c */ | 723 | /* cx88-mpeg.c */ |
741 | 724 | ||
742 | int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev, | 725 | int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev, |
743 | struct cx88_buffer *buf, enum v4l2_field field); | 726 | struct cx88_buffer *buf); |
744 | void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); | 727 | void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf); |
745 | void cx8802_cancel_buffers(struct cx8802_dev *dev); | 728 | void cx8802_cancel_buffers(struct cx8802_dev *dev); |
729 | int cx8802_start_dma(struct cx8802_dev *dev, | ||
730 | struct cx88_dmaqueue *q, | ||
731 | struct cx88_buffer *buf); | ||
746 | 732 | ||
747 | /* ----------------------------------------------------------- */ | 733 | /* ----------------------------------------------------------- */ |
748 | /* cx88-video.c*/ | 734 | /* cx88-video.c*/ |
749 | int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i); | 735 | int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i); |
750 | int cx88_set_freq(struct cx88_core *core, const struct v4l2_frequency *f); | 736 | int cx88_set_freq(struct cx88_core *core, const struct v4l2_frequency *f); |
751 | int cx88_video_mux(struct cx88_core *core, unsigned int input); | 737 | int cx88_video_mux(struct cx88_core *core, unsigned int input); |
752 | void cx88_querycap(struct file *file, struct cx88_core *core, | 738 | void cx88_querycap(struct file *file, struct cx88_core *core, |