diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-04-25 09:28:18 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-04-25 09:28:18 -0400 |
commit | a5d0568e2a686684ecdd1d6cb4edc48bceace249 (patch) | |
tree | 08977650478c56476eec6f7a94affa7f5f6067fc /drivers/media | |
parent | 966a1601877c3d29065ab2dde838cdae16ccc099 (diff) | |
parent | 486a7a2813c7d6e0b864c4b51027bcae3359071e (diff) |
Merge branch 'topic/cx25821' into patchwork
* topic/cx25821: (31 commits)
[media] cx25821: remove cx25821-audio-upstream.c from the Makefile
[media] cx25821: replace custom ioctls with write()
[media] cx25821: drop cx25821-video-upstream-ch2.c/h
[media] cx25821: add output format ioctls
[media] cx25821: prepare querycap for output support
[media] cx25821: group all fmt functions together
[media] cx25821: setup output nodes correctly
[media] cx25821: remove references to subdevices that aren't there
[media] cx25821: remove custom ioctls that duplicate v4l2 ioctls
[media] cx25821: g/s/try/enum_fmt related fixes and cleanups
[media] cx25821: switch to v4l2_fh, add event and prio handling
[media] cx25821: replace resource management functions with fh ownership
[media] cx25821: move vidq from cx25821_fh to cx25821_channel
[media] cx25821: remove 'type' field from cx25821_fh
[media] cx25821: use core locking
[media] cx25821: remove unnecessary debug messages
[media] cx25821: remove TRUE/FALSE/STATUS_(UN)SUCCESSFUL defines
[media] cx25821: convert to the control framework
[media] cx25821: embed video_device, clean up some kernel log spam
[media] cx25821: remove bogus dependencies
...
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/pci/cx25821/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/Makefile | 7 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-alsa.c | 81 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-audio-upstream.c | 22 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-cards.c | 23 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-core.c | 133 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-gpio.c | 1 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-i2c.c | 3 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-medusa-video.c | 46 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c | 800 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h | 138 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video-upstream.c | 519 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video.c | 1818 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821-video.h | 125 | ||||
-rw-r--r-- | drivers/media/pci/cx25821/cx25821.h | 304 |
15 files changed, 782 insertions, 3245 deletions
diff --git a/drivers/media/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig index 4017c9420348..6439a847680c 100644 --- a/drivers/media/pci/cx25821/Kconfig +++ b/drivers/media/pci/cx25821/Kconfig | |||
@@ -1,14 +1,9 @@ | |||
1 | config VIDEO_CX25821 | 1 | config VIDEO_CX25821 |
2 | tristate "Conexant cx25821 support" | 2 | tristate "Conexant cx25821 support" |
3 | depends on DVB_CORE && VIDEO_DEV && PCI && I2C | 3 | depends on VIDEO_DEV && PCI && I2C |
4 | select I2C_ALGOBIT | 4 | select I2C_ALGOBIT |
5 | select VIDEO_BTCX | 5 | select VIDEO_BTCX |
6 | select VIDEO_TVEEPROM | ||
7 | depends on RC_CORE | ||
8 | select VIDEOBUF_DVB | ||
9 | select VIDEOBUF_DMA_SG | 6 | select VIDEOBUF_DMA_SG |
10 | select VIDEO_CX25840 | ||
11 | select VIDEO_CX2341X | ||
12 | ---help--- | 7 | ---help--- |
13 | This is a video4linux driver for Conexant 25821 based | 8 | This is a video4linux driver for Conexant 25821 based |
14 | TV cards. | 9 | TV cards. |
diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile index caa32b7b51f8..fb76c3d3713a 100644 --- a/drivers/media/pci/cx25821/Makefile +++ b/drivers/media/pci/cx25821/Makefile | |||
@@ -1,14 +1,9 @@ | |||
1 | cx25821-y := cx25821-core.o cx25821-cards.o cx25821-i2c.o \ | 1 | cx25821-y := cx25821-core.o cx25821-cards.o cx25821-i2c.o \ |
2 | cx25821-gpio.o cx25821-medusa-video.o \ | 2 | cx25821-gpio.o cx25821-medusa-video.o \ |
3 | cx25821-video.o cx25821-video-upstream.o \ | 3 | cx25821-video.o cx25821-video-upstream.o |
4 | cx25821-video-upstream-ch2.o \ | ||
5 | cx25821-audio-upstream.o | ||
6 | 4 | ||
7 | obj-$(CONFIG_VIDEO_CX25821) += cx25821.o | 5 | obj-$(CONFIG_VIDEO_CX25821) += cx25821.o |
8 | obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o | 6 | obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o |
9 | 7 | ||
10 | ccflags-y += -Idrivers/media/i2c | 8 | ccflags-y += -Idrivers/media/i2c |
11 | ccflags-y += -Idrivers/media/common | 9 | ccflags-y += -Idrivers/media/common |
12 | ccflags-y += -Idrivers/media/tuners | ||
13 | ccflags-y += -Idrivers/media/dvb-core | ||
14 | ccflags-y += -Idrivers/media/dvb-frontends | ||
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c index 1858a45dd081..81361c26c54e 100644 --- a/drivers/media/pci/cx25821/cx25821-alsa.c +++ b/drivers/media/pci/cx25821/cx25821-alsa.c | |||
@@ -59,7 +59,6 @@ do { \ | |||
59 | Data type declarations - Can be moded to a header file later | 59 | Data type declarations - Can be moded to a header file later |
60 | ****************************************************************************/ | 60 | ****************************************************************************/ |
61 | 61 | ||
62 | static struct snd_card *snd_cx25821_cards[SNDRV_CARDS]; | ||
63 | static int devno; | 62 | static int devno; |
64 | 63 | ||
65 | struct cx25821_audio_buffer { | 64 | struct cx25821_audio_buffer { |
@@ -151,7 +150,7 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) | |||
151 | { | 150 | { |
152 | struct cx25821_audio_buffer *buf = chip->buf; | 151 | struct cx25821_audio_buffer *buf = chip->buf; |
153 | struct cx25821_dev *dev = chip->dev; | 152 | struct cx25821_dev *dev = chip->dev; |
154 | struct sram_channel *audio_ch = | 153 | const struct sram_channel *audio_ch = |
155 | &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; | 154 | &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]; |
156 | u32 tmp = 0; | 155 | u32 tmp = 0; |
157 | 156 | ||
@@ -627,34 +626,6 @@ static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = { | |||
627 | MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); | 626 | MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl); |
628 | 627 | ||
629 | /* | 628 | /* |
630 | * Not used in the function snd_cx25821_dev_free so removing | ||
631 | * from the file. | ||
632 | */ | ||
633 | /* | ||
634 | static int snd_cx25821_free(struct cx25821_audio_dev *chip) | ||
635 | { | ||
636 | if (chip->irq >= 0) | ||
637 | free_irq(chip->irq, chip); | ||
638 | |||
639 | cx25821_dev_unregister(chip->dev); | ||
640 | pci_disable_device(chip->pci); | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | */ | ||
645 | |||
646 | /* | ||
647 | * Component Destructor | ||
648 | */ | ||
649 | static void snd_cx25821_dev_free(struct snd_card *card) | ||
650 | { | ||
651 | struct cx25821_audio_dev *chip = card->private_data; | ||
652 | |||
653 | /* snd_cx25821_free(chip); */ | ||
654 | snd_card_free(chip->card); | ||
655 | } | ||
656 | |||
657 | /* | ||
658 | * Alsa Constructor - Component probe | 629 | * Alsa Constructor - Component probe |
659 | */ | 630 | */ |
660 | static int cx25821_audio_initdev(struct cx25821_dev *dev) | 631 | static int cx25821_audio_initdev(struct cx25821_dev *dev) |
@@ -685,7 +656,6 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
685 | strcpy(card->driver, "cx25821"); | 656 | strcpy(card->driver, "cx25821"); |
686 | 657 | ||
687 | /* Card "creation" */ | 658 | /* Card "creation" */ |
688 | card->private_free = snd_cx25821_dev_free; | ||
689 | chip = card->private_data; | 659 | chip = card->private_data; |
690 | spin_lock_init(&chip->reg_lock); | 660 | spin_lock_init(&chip->reg_lock); |
691 | 661 | ||
@@ -729,8 +699,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
729 | goto error; | 699 | goto error; |
730 | } | 700 | } |
731 | 701 | ||
732 | snd_cx25821_cards[devno] = card; | 702 | dev->card = card; |
733 | |||
734 | devno++; | 703 | devno++; |
735 | return 0; | 704 | return 0; |
736 | 705 | ||
@@ -742,9 +711,31 @@ error: | |||
742 | /**************************************************************************** | 711 | /**************************************************************************** |
743 | LINUX MODULE INIT | 712 | LINUX MODULE INIT |
744 | ****************************************************************************/ | 713 | ****************************************************************************/ |
714 | |||
715 | static int cx25821_alsa_exit_callback(struct device *dev, void *data) | ||
716 | { | ||
717 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); | ||
718 | struct cx25821_dev *cxdev = get_cx25821(v4l2_dev); | ||
719 | |||
720 | snd_card_free(cxdev->card); | ||
721 | return 0; | ||
722 | } | ||
723 | |||
745 | static void cx25821_audio_fini(void) | 724 | static void cx25821_audio_fini(void) |
746 | { | 725 | { |
747 | snd_card_free(snd_cx25821_cards[0]); | 726 | struct device_driver *drv = driver_find("cx25821", &pci_bus_type); |
727 | int ret; | ||
728 | |||
729 | ret = driver_for_each_device(drv, NULL, NULL, cx25821_alsa_exit_callback); | ||
730 | } | ||
731 | |||
732 | static int cx25821_alsa_init_callback(struct device *dev, void *data) | ||
733 | { | ||
734 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); | ||
735 | struct cx25821_dev *cxdev = get_cx25821(v4l2_dev); | ||
736 | |||
737 | cx25821_audio_initdev(cxdev); | ||
738 | return 0; | ||
748 | } | 739 | } |
749 | 740 | ||
750 | /* | 741 | /* |
@@ -756,29 +747,11 @@ static void cx25821_audio_fini(void) | |||
756 | */ | 747 | */ |
757 | static int cx25821_alsa_init(void) | 748 | static int cx25821_alsa_init(void) |
758 | { | 749 | { |
759 | struct cx25821_dev *dev = NULL; | 750 | struct device_driver *drv = driver_find("cx25821", &pci_bus_type); |
760 | struct list_head *list; | ||
761 | 751 | ||
762 | mutex_lock(&cx25821_devlist_mutex); | 752 | return driver_for_each_device(drv, NULL, NULL, cx25821_alsa_init_callback); |
763 | list_for_each(list, &cx25821_devlist) { | ||
764 | dev = list_entry(list, struct cx25821_dev, devlist); | ||
765 | cx25821_audio_initdev(dev); | ||
766 | } | ||
767 | mutex_unlock(&cx25821_devlist_mutex); | ||
768 | |||
769 | if (dev == NULL) | ||
770 | pr_info("ERROR ALSA: no cx25821 cards found\n"); | ||
771 | |||
772 | return 0; | ||
773 | 753 | ||
774 | } | 754 | } |
775 | 755 | ||
776 | late_initcall(cx25821_alsa_init); | 756 | late_initcall(cx25821_alsa_init); |
777 | module_exit(cx25821_audio_fini); | 757 | module_exit(cx25821_audio_fini); |
778 | |||
779 | /* ----------------------------------------------------------- */ | ||
780 | /* | ||
781 | * Local variables: | ||
782 | * c-basic-offset: 8 | ||
783 | * End: | ||
784 | */ | ||
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c index ea973202a66c..b9be535e32b8 100644 --- a/drivers/media/pci/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c | |||
@@ -45,7 +45,7 @@ static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | | |||
45 | FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR; | 45 | FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR; |
46 | 46 | ||
47 | static int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, | 47 | static int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, |
48 | struct sram_channel *ch, | 48 | const struct sram_channel *ch, |
49 | unsigned int bpl, u32 risc) | 49 | unsigned int bpl, u32 risc) |
50 | { | 50 | { |
51 | unsigned int i, lines; | 51 | unsigned int i, lines; |
@@ -106,7 +106,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, | |||
106 | int fifo_enable) | 106 | int fifo_enable) |
107 | { | 107 | { |
108 | unsigned int line; | 108 | unsigned int line; |
109 | struct sram_channel *sram_ch = | 109 | const struct sram_channel *sram_ch = |
110 | dev->channels[dev->_audio_upstream_channel].sram_channels; | 110 | dev->channels[dev->_audio_upstream_channel].sram_channels; |
111 | int offset = 0; | 111 | int offset = 0; |
112 | 112 | ||
@@ -215,7 +215,7 @@ static void cx25821_free_memory_audio(struct cx25821_dev *dev) | |||
215 | 215 | ||
216 | void cx25821_stop_upstream_audio(struct cx25821_dev *dev) | 216 | void cx25821_stop_upstream_audio(struct cx25821_dev *dev) |
217 | { | 217 | { |
218 | struct sram_channel *sram_ch = | 218 | const struct sram_channel *sram_ch = |
219 | dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; | 219 | dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; |
220 | u32 tmp = 0; | 220 | u32 tmp = 0; |
221 | 221 | ||
@@ -257,7 +257,7 @@ void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev) | |||
257 | } | 257 | } |
258 | 258 | ||
259 | static int cx25821_get_audio_data(struct cx25821_dev *dev, | 259 | static int cx25821_get_audio_data(struct cx25821_dev *dev, |
260 | struct sram_channel *sram_ch) | 260 | const struct sram_channel *sram_ch) |
261 | { | 261 | { |
262 | struct file *myfile; | 262 | struct file *myfile; |
263 | int frame_index_temp = dev->_audioframe_index; | 263 | int frame_index_temp = dev->_audioframe_index; |
@@ -352,7 +352,7 @@ static void cx25821_audioups_handler(struct work_struct *work) | |||
352 | } | 352 | } |
353 | 353 | ||
354 | static int cx25821_openfile_audio(struct cx25821_dev *dev, | 354 | static int cx25821_openfile_audio(struct cx25821_dev *dev, |
355 | struct sram_channel *sram_ch) | 355 | const struct sram_channel *sram_ch) |
356 | { | 356 | { |
357 | struct file *myfile; | 357 | struct file *myfile; |
358 | int i = 0, j = 0; | 358 | int i = 0, j = 0; |
@@ -433,7 +433,7 @@ static int cx25821_openfile_audio(struct cx25821_dev *dev, | |||
433 | } | 433 | } |
434 | 434 | ||
435 | static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | 435 | static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, |
436 | struct sram_channel *sram_ch, | 436 | const struct sram_channel *sram_ch, |
437 | int bpl) | 437 | int bpl) |
438 | { | 438 | { |
439 | int ret = 0; | 439 | int ret = 0; |
@@ -495,7 +495,7 @@ static int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
495 | { | 495 | { |
496 | int i = 0; | 496 | int i = 0; |
497 | u32 int_msk_tmp; | 497 | u32 int_msk_tmp; |
498 | struct sram_channel *channel = dev->channels[chan_num].sram_channels; | 498 | const struct sram_channel *channel = dev->channels[chan_num].sram_channels; |
499 | dma_addr_t risc_phys_jump_addr; | 499 | dma_addr_t risc_phys_jump_addr; |
500 | __le32 *rp; | 500 | __le32 *rp; |
501 | 501 | ||
@@ -587,7 +587,7 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) | |||
587 | struct cx25821_dev *dev = dev_id; | 587 | struct cx25821_dev *dev = dev_id; |
588 | u32 audio_status; | 588 | u32 audio_status; |
589 | int handled = 0; | 589 | int handled = 0; |
590 | struct sram_channel *sram_ch; | 590 | const struct sram_channel *sram_ch; |
591 | 591 | ||
592 | if (!dev) | 592 | if (!dev) |
593 | return -1; | 593 | return -1; |
@@ -611,7 +611,7 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) | |||
611 | } | 611 | } |
612 | 612 | ||
613 | static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, | 613 | static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, |
614 | struct sram_channel *sram_ch) | 614 | const struct sram_channel *sram_ch) |
615 | { | 615 | { |
616 | int count = 0; | 616 | int count = 0; |
617 | u32 tmp; | 617 | u32 tmp; |
@@ -635,7 +635,7 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, | |||
635 | } | 635 | } |
636 | 636 | ||
637 | static int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | 637 | static int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, |
638 | struct sram_channel *sram_ch) | 638 | const struct sram_channel *sram_ch) |
639 | { | 639 | { |
640 | u32 tmp = 0; | 640 | u32 tmp = 0; |
641 | int err = 0; | 641 | int err = 0; |
@@ -699,7 +699,7 @@ fail_irq: | |||
699 | 699 | ||
700 | int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | 700 | int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) |
701 | { | 701 | { |
702 | struct sram_channel *sram_ch; | 702 | const struct sram_channel *sram_ch; |
703 | int err = 0; | 703 | int err = 0; |
704 | 704 | ||
705 | if (dev->_audio_is_running) { | 705 | if (dev->_audio_is_running) { |
diff --git a/drivers/media/pci/cx25821/cx25821-cards.c b/drivers/media/pci/cx25821/cx25821-cards.c index 99988c988095..3b409feb03d8 100644 --- a/drivers/media/pci/cx25821/cx25821-cards.c +++ b/drivers/media/pci/cx25821/cx25821-cards.c | |||
@@ -26,11 +26,8 @@ | |||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/delay.h> | ||
30 | #include <media/cx25840.h> | ||
31 | 29 | ||
32 | #include "cx25821.h" | 30 | #include "cx25821.h" |
33 | #include "tuner-xc2028.h" | ||
34 | 31 | ||
35 | /* board config info */ | 32 | /* board config info */ |
36 | 33 | ||
@@ -45,28 +42,8 @@ struct cx25821_board cx25821_boards[] = { | |||
45 | .name = "CX25821", | 42 | .name = "CX25821", |
46 | .portb = CX25821_RAW, | 43 | .portb = CX25821_RAW, |
47 | .portc = CX25821_264, | 44 | .portc = CX25821_264, |
48 | .input[0].type = CX25821_VMUX_COMPOSITE, | ||
49 | }, | 45 | }, |
50 | 46 | ||
51 | }; | 47 | }; |
52 | 48 | ||
53 | const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards); | 49 | const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards); |
54 | |||
55 | struct cx25821_subid cx25821_subids[] = { | ||
56 | { | ||
57 | .subvendor = 0x14f1, | ||
58 | .subdevice = 0x0920, | ||
59 | .card = CX25821_BOARD, | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | void cx25821_card_setup(struct cx25821_dev *dev) | ||
64 | { | ||
65 | static u8 eeprom[256]; | ||
66 | |||
67 | if (dev->i2c_bus[0].i2c_rc == 0) { | ||
68 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; | ||
69 | tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, | ||
70 | sizeof(eeprom)); | ||
71 | } | ||
72 | } | ||
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 1884e2cc35e9..b762c5b2ca10 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c | |||
@@ -41,14 +41,7 @@ static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | |||
41 | module_param_array(card, int, NULL, 0444); | 41 | module_param_array(card, int, NULL, 0444); |
42 | MODULE_PARM_DESC(card, "card type"); | 42 | MODULE_PARM_DESC(card, "card type"); |
43 | 43 | ||
44 | static unsigned int cx25821_devcount; | 44 | const struct sram_channel cx25821_sram_channels[] = { |
45 | |||
46 | DEFINE_MUTEX(cx25821_devlist_mutex); | ||
47 | EXPORT_SYMBOL(cx25821_devlist_mutex); | ||
48 | LIST_HEAD(cx25821_devlist); | ||
49 | EXPORT_SYMBOL(cx25821_devlist); | ||
50 | |||
51 | struct sram_channel cx25821_sram_channels[] = { | ||
52 | [SRAM_CH00] = { | 45 | [SRAM_CH00] = { |
53 | .i = SRAM_CH00, | 46 | .i = SRAM_CH00, |
54 | .name = "VID A", | 47 | .name = "VID A", |
@@ -317,20 +310,6 @@ struct sram_channel cx25821_sram_channels[] = { | |||
317 | }; | 310 | }; |
318 | EXPORT_SYMBOL(cx25821_sram_channels); | 311 | EXPORT_SYMBOL(cx25821_sram_channels); |
319 | 312 | ||
320 | struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00]; | ||
321 | struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01]; | ||
322 | struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02]; | ||
323 | struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03]; | ||
324 | struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04]; | ||
325 | struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05]; | ||
326 | struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06]; | ||
327 | struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07]; | ||
328 | struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09]; | ||
329 | struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10]; | ||
330 | struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11]; | ||
331 | |||
332 | struct cx25821_dmaqueue mpegq; | ||
333 | |||
334 | static int cx25821_risc_decode(u32 risc) | 313 | static int cx25821_risc_decode(u32 risc) |
335 | { | 314 | { |
336 | static const char * const instr[16] = { | 315 | static const char * const instr[16] = { |
@@ -457,7 +436,7 @@ static void cx25821_registers_init(struct cx25821_dev *dev) | |||
457 | } | 436 | } |
458 | 437 | ||
459 | int cx25821_sram_channel_setup(struct cx25821_dev *dev, | 438 | int cx25821_sram_channel_setup(struct cx25821_dev *dev, |
460 | struct sram_channel *ch, | 439 | const struct sram_channel *ch, |
461 | unsigned int bpl, u32 risc) | 440 | unsigned int bpl, u32 risc) |
462 | { | 441 | { |
463 | unsigned int i, lines; | 442 | unsigned int i, lines; |
@@ -523,10 +502,9 @@ int cx25821_sram_channel_setup(struct cx25821_dev *dev, | |||
523 | 502 | ||
524 | return 0; | 503 | return 0; |
525 | } | 504 | } |
526 | EXPORT_SYMBOL(cx25821_sram_channel_setup); | ||
527 | 505 | ||
528 | int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | 506 | int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, |
529 | struct sram_channel *ch, | 507 | const struct sram_channel *ch, |
530 | unsigned int bpl, u32 risc) | 508 | unsigned int bpl, u32 risc) |
531 | { | 509 | { |
532 | unsigned int i, lines; | 510 | unsigned int i, lines; |
@@ -592,7 +570,7 @@ int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | |||
592 | } | 570 | } |
593 | EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); | 571 | EXPORT_SYMBOL(cx25821_sram_channel_setup_audio); |
594 | 572 | ||
595 | void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) | 573 | void cx25821_sram_channel_dump(struct cx25821_dev *dev, const struct sram_channel *ch) |
596 | { | 574 | { |
597 | static char *name[] = { | 575 | static char *name[] = { |
598 | "init risc lo", | 576 | "init risc lo", |
@@ -652,10 +630,9 @@ void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch) | |||
652 | pr_warn(" : cnt2_reg: 0x%08x\n", | 630 | pr_warn(" : cnt2_reg: 0x%08x\n", |
653 | cx_read(ch->cnt2_reg)); | 631 | cx_read(ch->cnt2_reg)); |
654 | } | 632 | } |
655 | EXPORT_SYMBOL(cx25821_sram_channel_dump); | ||
656 | 633 | ||
657 | void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | 634 | void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, |
658 | struct sram_channel *ch) | 635 | const struct sram_channel *ch) |
659 | { | 636 | { |
660 | static const char * const name[] = { | 637 | static const char * const name[] = { |
661 | "init risc lo", | 638 | "init risc lo", |
@@ -798,12 +775,12 @@ void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, | |||
798 | if (channel_select <= 7 && channel_select >= 0) { | 775 | if (channel_select <= 7 && channel_select >= 0) { |
799 | cx_write(dev->channels[channel_select].sram_channels->pix_frmt, | 776 | cx_write(dev->channels[channel_select].sram_channels->pix_frmt, |
800 | format); | 777 | format); |
801 | dev->channels[channel_select].pixel_formats = format; | ||
802 | } | 778 | } |
779 | dev->channels[channel_select].pixel_formats = format; | ||
803 | } | 780 | } |
804 | 781 | ||
805 | static void cx25821_set_vip_mode(struct cx25821_dev *dev, | 782 | static void cx25821_set_vip_mode(struct cx25821_dev *dev, |
806 | struct sram_channel *ch) | 783 | const struct sram_channel *ch) |
807 | { | 784 | { |
808 | cx_write(ch->pix_frmt, PIXEL_FRMT_422); | 785 | cx_write(ch->pix_frmt, PIXEL_FRMT_422); |
809 | cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); | 786 | cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1); |
@@ -837,12 +814,13 @@ static void cx25821_initialize(struct cx25821_dev *dev) | |||
837 | cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels, | 814 | cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels, |
838 | 1440, 0); | 815 | 1440, 0); |
839 | dev->channels[i].pixel_formats = PIXEL_FRMT_422; | 816 | dev->channels[i].pixel_formats = PIXEL_FRMT_422; |
840 | dev->channels[i].use_cif_resolution = FALSE; | 817 | dev->channels[i].use_cif_resolution = 0; |
841 | } | 818 | } |
842 | 819 | ||
843 | /* Probably only affect Downstream */ | 820 | /* Probably only affect Downstream */ |
844 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; | 821 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; |
845 | i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { | 822 | i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { |
823 | dev->channels[i].pixel_formats = PIXEL_FRMT_422; | ||
846 | cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); | 824 | cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); |
847 | } | 825 | } |
848 | 826 | ||
@@ -868,8 +846,7 @@ static void cx25821_dev_checkrevision(struct cx25821_dev *dev) | |||
868 | { | 846 | { |
869 | dev->hwrevision = cx_read(RDR_CFG2) & 0xff; | 847 | dev->hwrevision = cx_read(RDR_CFG2) & 0xff; |
870 | 848 | ||
871 | pr_info("%s(): Hardware revision = 0x%02x\n", | 849 | pr_info("Hardware revision = 0x%02x\n", dev->hwrevision); |
872 | __func__, dev->hwrevision); | ||
873 | } | 850 | } |
874 | 851 | ||
875 | static void cx25821_iounmap(struct cx25821_dev *dev) | 852 | static void cx25821_iounmap(struct cx25821_dev *dev) |
@@ -879,7 +856,6 @@ static void cx25821_iounmap(struct cx25821_dev *dev) | |||
879 | 856 | ||
880 | /* Releasing IO memory */ | 857 | /* Releasing IO memory */ |
881 | if (dev->lmmio != NULL) { | 858 | if (dev->lmmio != NULL) { |
882 | CX25821_INFO("Releasing lmmio.\n"); | ||
883 | iounmap(dev->lmmio); | 859 | iounmap(dev->lmmio); |
884 | dev->lmmio = NULL; | 860 | dev->lmmio = NULL; |
885 | } | 861 | } |
@@ -887,23 +863,14 @@ static void cx25821_iounmap(struct cx25821_dev *dev) | |||
887 | 863 | ||
888 | static int cx25821_dev_setup(struct cx25821_dev *dev) | 864 | static int cx25821_dev_setup(struct cx25821_dev *dev) |
889 | { | 865 | { |
866 | static unsigned int cx25821_devcount; | ||
890 | int i; | 867 | int i; |
891 | 868 | ||
892 | pr_info("\n***********************************\n"); | ||
893 | pr_info("cx25821 set up\n"); | ||
894 | pr_info("***********************************\n\n"); | ||
895 | |||
896 | mutex_init(&dev->lock); | 869 | mutex_init(&dev->lock); |
897 | 870 | ||
898 | atomic_inc(&dev->refcount); | ||
899 | |||
900 | dev->nr = ++cx25821_devcount; | 871 | dev->nr = ++cx25821_devcount; |
901 | sprintf(dev->name, "cx25821[%d]", dev->nr); | 872 | sprintf(dev->name, "cx25821[%d]", dev->nr); |
902 | 873 | ||
903 | mutex_lock(&cx25821_devlist_mutex); | ||
904 | list_add_tail(&dev->devlist, &cx25821_devlist); | ||
905 | mutex_unlock(&cx25821_devlist_mutex); | ||
906 | |||
907 | if (dev->pci->device != 0x8210) { | 874 | if (dev->pci->device != 0x8210) { |
908 | pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", | 875 | pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", |
909 | __func__, dev->pci->device); | 876 | __func__, dev->pci->device); |
@@ -914,8 +881,11 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
914 | 881 | ||
915 | /* Apply a sensible clock frequency for the PCIe bridge */ | 882 | /* Apply a sensible clock frequency for the PCIe bridge */ |
916 | dev->clk_freq = 28000000; | 883 | dev->clk_freq = 28000000; |
917 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) | 884 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { |
885 | dev->channels[i].dev = dev; | ||
886 | dev->channels[i].id = i; | ||
918 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; | 887 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; |
888 | } | ||
919 | 889 | ||
920 | if (dev->nr > 1) | 890 | if (dev->nr > 1) |
921 | CX25821_INFO("dev->nr > 1!"); | 891 | CX25821_INFO("dev->nr > 1!"); |
@@ -978,63 +948,15 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
978 | /* cx25821_i2c_register(&dev->i2c_bus[1]); | 948 | /* cx25821_i2c_register(&dev->i2c_bus[1]); |
979 | * cx25821_i2c_register(&dev->i2c_bus[2]); */ | 949 | * cx25821_i2c_register(&dev->i2c_bus[2]); */ |
980 | 950 | ||
981 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", | ||
982 | dev->i2c_bus[0].i2c_rc); | ||
983 | |||
984 | cx25821_card_setup(dev); | ||
985 | |||
986 | if (medusa_video_init(dev) < 0) | 951 | if (medusa_video_init(dev) < 0) |
987 | CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__); | 952 | CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__); |
988 | 953 | ||
989 | cx25821_video_register(dev); | 954 | cx25821_video_register(dev); |
990 | 955 | ||
991 | /* register IOCTL device */ | ||
992 | dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, | ||
993 | &cx25821_videoioctl_template, "video"); | ||
994 | |||
995 | if (video_register_device | ||
996 | (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { | ||
997 | cx25821_videoioctl_unregister(dev); | ||
998 | pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n", | ||
999 | __func__); | ||
1000 | } | ||
1001 | |||
1002 | cx25821_dev_checkrevision(dev); | 956 | cx25821_dev_checkrevision(dev); |
1003 | CX25821_INFO("setup done!\n"); | ||
1004 | |||
1005 | return 0; | 957 | return 0; |
1006 | } | 958 | } |
1007 | 959 | ||
1008 | void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, | ||
1009 | struct upstream_user_struct *up_data) | ||
1010 | { | ||
1011 | dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0; | ||
1012 | |||
1013 | dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
1014 | medusa_set_videostandard(dev); | ||
1015 | |||
1016 | cx25821_vidupstream_init_ch1(dev, dev->channel_select, | ||
1017 | dev->pixel_format); | ||
1018 | } | ||
1019 | |||
1020 | void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, | ||
1021 | struct upstream_user_struct *up_data) | ||
1022 | { | ||
1023 | dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0; | ||
1024 | |||
1025 | dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M; | ||
1026 | medusa_set_videostandard(dev); | ||
1027 | |||
1028 | cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2, | ||
1029 | dev->pixel_format_ch2); | ||
1030 | } | ||
1031 | |||
1032 | void cx25821_start_upstream_audio(struct cx25821_dev *dev, | ||
1033 | struct upstream_user_struct *up_data) | ||
1034 | { | ||
1035 | cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B); | ||
1036 | } | ||
1037 | |||
1038 | void cx25821_dev_unregister(struct cx25821_dev *dev) | 960 | void cx25821_dev_unregister(struct cx25821_dev *dev) |
1039 | { | 961 | { |
1040 | int i; | 962 | int i; |
@@ -1042,25 +964,16 @@ void cx25821_dev_unregister(struct cx25821_dev *dev) | |||
1042 | if (!dev->base_io_addr) | 964 | if (!dev->base_io_addr) |
1043 | return; | 965 | return; |
1044 | 966 | ||
1045 | cx25821_free_mem_upstream_ch1(dev); | ||
1046 | cx25821_free_mem_upstream_ch2(dev); | ||
1047 | cx25821_free_mem_upstream_audio(dev); | ||
1048 | |||
1049 | release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); | 967 | release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0)); |
1050 | 968 | ||
1051 | if (!atomic_dec_and_test(&dev->refcount)) | 969 | for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; i++) { |
1052 | return; | 970 | if (i == SRAM_CH08) /* audio channel */ |
1053 | 971 | continue; | |
1054 | for (i = 0; i < VID_CHANNEL_NUM; i++) | 972 | if (i == SRAM_CH09 || i == SRAM_CH10) |
1055 | cx25821_video_unregister(dev, i); | 973 | cx25821_free_mem_upstream(&dev->channels[i]); |
1056 | |||
1057 | for (i = VID_UPSTREAM_SRAM_CHANNEL_I; | ||
1058 | i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) { | ||
1059 | cx25821_video_unregister(dev, i); | 974 | cx25821_video_unregister(dev, i); |
1060 | } | 975 | } |
1061 | 976 | ||
1062 | cx25821_videoioctl_unregister(dev); | ||
1063 | |||
1064 | cx25821_i2c_unregister(&dev->i2c_bus[0]); | 977 | cx25821_i2c_unregister(&dev->i2c_bus[0]); |
1065 | cx25821_iounmap(dev); | 978 | cx25821_iounmap(dev); |
1066 | } | 979 | } |
@@ -1385,8 +1298,6 @@ static int cx25821_initdev(struct pci_dev *pci_dev, | |||
1385 | goto fail_unregister_device; | 1298 | goto fail_unregister_device; |
1386 | } | 1299 | } |
1387 | 1300 | ||
1388 | pr_info("Athena pci enable !\n"); | ||
1389 | |||
1390 | err = cx25821_dev_setup(dev); | 1301 | err = cx25821_dev_setup(dev); |
1391 | if (err) { | 1302 | if (err) { |
1392 | if (err == -EBUSY) | 1303 | if (err == -EBUSY) |
@@ -1445,10 +1356,6 @@ static void cx25821_finidev(struct pci_dev *pci_dev) | |||
1445 | if (pci_dev->irq) | 1356 | if (pci_dev->irq) |
1446 | free_irq(pci_dev->irq, dev); | 1357 | free_irq(pci_dev->irq, dev); |
1447 | 1358 | ||
1448 | mutex_lock(&cx25821_devlist_mutex); | ||
1449 | list_del(&dev->devlist); | ||
1450 | mutex_unlock(&cx25821_devlist_mutex); | ||
1451 | |||
1452 | cx25821_dev_unregister(dev); | 1359 | cx25821_dev_unregister(dev); |
1453 | v4l2_device_unregister(v4l2_dev); | 1360 | v4l2_device_unregister(v4l2_dev); |
1454 | kfree(dev); | 1361 | kfree(dev); |
diff --git a/drivers/media/pci/cx25821/cx25821-gpio.c b/drivers/media/pci/cx25821/cx25821-gpio.c index 29e43b03c85e..95e8ddf62947 100644 --- a/drivers/media/pci/cx25821/cx25821-gpio.c +++ b/drivers/media/pci/cx25821/cx25821-gpio.c | |||
@@ -20,6 +20,7 @@ | |||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | ||
23 | #include "cx25821.h" | 24 | #include "cx25821.h" |
24 | 25 | ||
25 | /********************* GPIO stuffs *********************/ | 26 | /********************* GPIO stuffs *********************/ |
diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c index a8dc945bbe17..dca37c7dba73 100644 --- a/drivers/media/pci/cx25821/cx25821-i2c.c +++ b/drivers/media/pci/cx25821/cx25821-i2c.c | |||
@@ -23,8 +23,9 @@ | |||
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
25 | 25 | ||
26 | #include "cx25821.h" | 26 | #include <linux/module.h> |
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include "cx25821.h" | ||
28 | 29 | ||
29 | static unsigned int i2c_debug; | 30 | static unsigned int i2c_debug; |
30 | module_param(i2c_debug, int, 0644); | 31 | module_param(i2c_debug, int, 0644); |
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.c b/drivers/media/pci/cx25821/cx25821-medusa-video.c index 6a92e5c70c2a..22fa04415ccc 100644 --- a/drivers/media/pci/cx25821/cx25821-medusa-video.c +++ b/drivers/media/pci/cx25821/cx25821-medusa-video.c | |||
@@ -94,8 +94,6 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
94 | u32 value = 0; | 94 | u32 value = 0; |
95 | u32 tmp = 0; | 95 | u32 tmp = 0; |
96 | 96 | ||
97 | mutex_lock(&dev->lock); | ||
98 | |||
99 | for (i = 0; i < MAX_DECODERS; i++) { | 97 | for (i = 0; i < MAX_DECODERS; i++) { |
100 | /* set video format NTSC-M */ | 98 | /* set video format NTSC-M */ |
101 | value = cx25821_i2c_read(&dev->i2c_bus[0], | 99 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
@@ -222,8 +220,6 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
222 | value |= 0x00080200; | 220 | value |= 0x00080200; |
223 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | 221 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); |
224 | 222 | ||
225 | mutex_unlock(&dev->lock); | ||
226 | |||
227 | return ret_val; | 223 | return ret_val; |
228 | } | 224 | } |
229 | 225 | ||
@@ -265,8 +261,6 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
265 | u32 value = 0; | 261 | u32 value = 0; |
266 | u32 tmp = 0; | 262 | u32 tmp = 0; |
267 | 263 | ||
268 | mutex_lock(&dev->lock); | ||
269 | |||
270 | for (i = 0; i < MAX_DECODERS; i++) { | 264 | for (i = 0; i < MAX_DECODERS; i++) { |
271 | /* set video format PAL-BDGHI */ | 265 | /* set video format PAL-BDGHI */ |
272 | value = cx25821_i2c_read(&dev->i2c_bus[0], | 266 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
@@ -397,14 +391,12 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
397 | value &= 0xFFF7FDFF; | 391 | value &= 0xFFF7FDFF; |
398 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | 392 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); |
399 | 393 | ||
400 | mutex_unlock(&dev->lock); | ||
401 | |||
402 | return ret_val; | 394 | return ret_val; |
403 | } | 395 | } |
404 | 396 | ||
405 | int medusa_set_videostandard(struct cx25821_dev *dev) | 397 | int medusa_set_videostandard(struct cx25821_dev *dev) |
406 | { | 398 | { |
407 | int status = STATUS_SUCCESS; | 399 | int status = 0; |
408 | u32 value = 0, tmp = 0; | 400 | u32 value = 0, tmp = 0; |
409 | 401 | ||
410 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | 402 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) |
@@ -434,8 +426,6 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, | |||
434 | u32 vscale = 0x0; | 426 | u32 vscale = 0x0; |
435 | const int MAX_WIDTH = 720; | 427 | const int MAX_WIDTH = 720; |
436 | 428 | ||
437 | mutex_lock(&dev->lock); | ||
438 | |||
439 | /* validate the width */ | 429 | /* validate the width */ |
440 | if (width > MAX_WIDTH) { | 430 | if (width > MAX_WIDTH) { |
441 | pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", | 431 | pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", |
@@ -485,8 +475,6 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, | |||
485 | cx25821_i2c_write(&dev->i2c_bus[0], | 475 | cx25821_i2c_write(&dev->i2c_bus[0], |
486 | VSCALE_CTRL + (0x200 * decoder), vscale); | 476 | VSCALE_CTRL + (0x200 * decoder), vscale); |
487 | } | 477 | } |
488 | |||
489 | mutex_unlock(&dev->lock); | ||
490 | } | 478 | } |
491 | 479 | ||
492 | static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | 480 | static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, |
@@ -496,11 +484,8 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | |||
496 | u32 tmp = 0; | 484 | u32 tmp = 0; |
497 | u32 disp_cnt_reg = DISP_AB_CNT; | 485 | u32 disp_cnt_reg = DISP_AB_CNT; |
498 | 486 | ||
499 | mutex_lock(&dev->lock); | ||
500 | |||
501 | /* no support */ | 487 | /* no support */ |
502 | if (decoder < VDEC_A || decoder > VDEC_H) { | 488 | if (decoder < VDEC_A || decoder > VDEC_H) { |
503 | mutex_unlock(&dev->lock); | ||
504 | return; | 489 | return; |
505 | } | 490 | } |
506 | 491 | ||
@@ -535,8 +520,6 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | |||
535 | } | 520 | } |
536 | 521 | ||
537 | cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); | 522 | cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); |
538 | |||
539 | mutex_unlock(&dev->lock); | ||
540 | } | 523 | } |
541 | 524 | ||
542 | /* Map to Medusa register setting */ | 525 | /* Map to Medusa register setting */ |
@@ -587,10 +570,8 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | |||
587 | int value = 0; | 570 | int value = 0; |
588 | u32 val = 0, tmp = 0; | 571 | u32 val = 0, tmp = 0; |
589 | 572 | ||
590 | mutex_lock(&dev->lock); | ||
591 | if ((brightness > VIDEO_PROCAMP_MAX) || | 573 | if ((brightness > VIDEO_PROCAMP_MAX) || |
592 | (brightness < VIDEO_PROCAMP_MIN)) { | 574 | (brightness < VIDEO_PROCAMP_MIN)) { |
593 | mutex_unlock(&dev->lock); | ||
594 | return -1; | 575 | return -1; |
595 | } | 576 | } |
596 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, | 577 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, |
@@ -601,7 +582,6 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | |||
601 | val &= 0xFFFFFF00; | 582 | val &= 0xFFFFFF00; |
602 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], | 583 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
603 | VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value); | 584 | VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value); |
604 | mutex_unlock(&dev->lock); | ||
605 | return ret_val; | 585 | return ret_val; |
606 | } | 586 | } |
607 | 587 | ||
@@ -611,10 +591,7 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | |||
611 | int value = 0; | 591 | int value = 0; |
612 | u32 val = 0, tmp = 0; | 592 | u32 val = 0, tmp = 0; |
613 | 593 | ||
614 | mutex_lock(&dev->lock); | ||
615 | |||
616 | if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) { | 594 | if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) { |
617 | mutex_unlock(&dev->lock); | ||
618 | return -1; | 595 | return -1; |
619 | } | 596 | } |
620 | 597 | ||
@@ -626,7 +603,6 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | |||
626 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], | 603 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
627 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value); | 604 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value); |
628 | 605 | ||
629 | mutex_unlock(&dev->lock); | ||
630 | return ret_val; | 606 | return ret_val; |
631 | } | 607 | } |
632 | 608 | ||
@@ -636,10 +612,7 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | |||
636 | int value = 0; | 612 | int value = 0; |
637 | u32 val = 0, tmp = 0; | 613 | u32 val = 0, tmp = 0; |
638 | 614 | ||
639 | mutex_lock(&dev->lock); | ||
640 | |||
641 | if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) { | 615 | if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) { |
642 | mutex_unlock(&dev->lock); | ||
643 | return -1; | 616 | return -1; |
644 | } | 617 | } |
645 | 618 | ||
@@ -654,7 +627,6 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | |||
654 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], | 627 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
655 | VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); | 628 | VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); |
656 | 629 | ||
657 | mutex_unlock(&dev->lock); | ||
658 | return ret_val; | 630 | return ret_val; |
659 | } | 631 | } |
660 | 632 | ||
@@ -664,11 +636,8 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | |||
664 | int value = 0; | 636 | int value = 0; |
665 | u32 val = 0, tmp = 0; | 637 | u32 val = 0, tmp = 0; |
666 | 638 | ||
667 | mutex_lock(&dev->lock); | ||
668 | |||
669 | if ((saturation > VIDEO_PROCAMP_MAX) || | 639 | if ((saturation > VIDEO_PROCAMP_MAX) || |
670 | (saturation < VIDEO_PROCAMP_MIN)) { | 640 | (saturation < VIDEO_PROCAMP_MIN)) { |
671 | mutex_unlock(&dev->lock); | ||
672 | return -1; | 641 | return -1; |
673 | } | 642 | } |
674 | 643 | ||
@@ -687,7 +656,6 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | |||
687 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], | 656 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
688 | VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value); | 657 | VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value); |
689 | 658 | ||
690 | mutex_unlock(&dev->lock); | ||
691 | return ret_val; | 659 | return ret_val; |
692 | } | 660 | } |
693 | 661 | ||
@@ -699,8 +667,6 @@ int medusa_video_init(struct cx25821_dev *dev) | |||
699 | int ret_val = 0; | 667 | int ret_val = 0; |
700 | int i = 0; | 668 | int i = 0; |
701 | 669 | ||
702 | mutex_lock(&dev->lock); | ||
703 | |||
704 | _num_decoders = dev->_max_num_decoders; | 670 | _num_decoders = dev->_max_num_decoders; |
705 | 671 | ||
706 | /* disable Auto source selection on all video decoders */ | 672 | /* disable Auto source selection on all video decoders */ |
@@ -719,13 +685,9 @@ int medusa_video_init(struct cx25821_dev *dev) | |||
719 | if (ret_val < 0) | 685 | if (ret_val < 0) |
720 | goto error; | 686 | goto error; |
721 | 687 | ||
722 | mutex_unlock(&dev->lock); | ||
723 | |||
724 | for (i = 0; i < _num_decoders; i++) | 688 | for (i = 0; i < _num_decoders; i++) |
725 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); | 689 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); |
726 | 690 | ||
727 | mutex_lock(&dev->lock); | ||
728 | |||
729 | /* Select monitor as DENC A input, power up the DAC */ | 691 | /* Select monitor as DENC A input, power up the DAC */ |
730 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); | 692 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); |
731 | value &= 0xFF70FF70; | 693 | value &= 0xFF70FF70; |
@@ -774,14 +736,8 @@ int medusa_video_init(struct cx25821_dev *dev) | |||
774 | if (ret_val < 0) | 736 | if (ret_val < 0) |
775 | goto error; | 737 | goto error; |
776 | 738 | ||
777 | |||
778 | mutex_unlock(&dev->lock); | ||
779 | |||
780 | ret_val = medusa_set_videostandard(dev); | 739 | ret_val = medusa_set_videostandard(dev); |
781 | 740 | ||
782 | return ret_val; | ||
783 | |||
784 | error: | 741 | error: |
785 | mutex_unlock(&dev->lock); | ||
786 | return ret_val; | 742 | return ret_val; |
787 | } | 743 | } |
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c deleted file mode 100644 index cf2723c7197f..000000000000 --- a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c +++ /dev/null | |||
@@ -1,800 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
24 | |||
25 | #include "cx25821-video.h" | ||
26 | #include "cx25821-video-upstream-ch2.h" | ||
27 | |||
28 | #include <linux/fs.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/syscalls.h> | ||
34 | #include <linux/file.h> | ||
35 | #include <linux/fcntl.h> | ||
36 | #include <linux/slab.h> | ||
37 | #include <linux/uaccess.h> | ||
38 | |||
39 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | ||
40 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | ||
41 | MODULE_LICENSE("GPL"); | ||
42 | |||
43 | static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | | ||
44 | FLD_VID_SRC_OPC_ERR; | ||
45 | |||
46 | static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, | ||
47 | __le32 *rp, unsigned int offset, | ||
48 | unsigned int bpl, u32 sync_line, | ||
49 | unsigned int lines, | ||
50 | int fifo_enable, int field_type) | ||
51 | { | ||
52 | unsigned int line, i; | ||
53 | int dist_betwn_starts = bpl * 2; | ||
54 | |||
55 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
56 | |||
57 | if (USE_RISC_NOOP_VIDEO) { | ||
58 | for (i = 0; i < NUM_NO_OPS; i++) | ||
59 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
60 | } | ||
61 | |||
62 | /* scan lines */ | ||
63 | for (line = 0; line < lines; line++) { | ||
64 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
65 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset); | ||
66 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
67 | |||
68 | if ((lines <= NTSC_FIELD_HEIGHT) || | ||
69 | (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) { | ||
70 | offset += dist_betwn_starts; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | return rp; | ||
75 | } | ||
76 | |||
77 | static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, | ||
78 | __le32 *rp, | ||
79 | dma_addr_t databuf_phys_addr, | ||
80 | unsigned int offset, | ||
81 | u32 sync_line, unsigned int bpl, | ||
82 | unsigned int lines, | ||
83 | int fifo_enable, int field_type) | ||
84 | { | ||
85 | unsigned int line, i; | ||
86 | struct sram_channel *sram_ch = | ||
87 | dev->channels[dev->_channel2_upstream_select].sram_channels; | ||
88 | int dist_betwn_starts = bpl * 2; | ||
89 | |||
90 | /* sync instruction */ | ||
91 | if (sync_line != NO_SYNC_LINE) | ||
92 | *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); | ||
93 | |||
94 | if (USE_RISC_NOOP_VIDEO) { | ||
95 | for (i = 0; i < NUM_NO_OPS; i++) | ||
96 | *(rp++) = cpu_to_le32(RISC_NOOP); | ||
97 | } | ||
98 | |||
99 | /* scan lines */ | ||
100 | for (line = 0; line < lines; line++) { | ||
101 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | ||
102 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | ||
103 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | ||
104 | |||
105 | if ((lines <= NTSC_FIELD_HEIGHT) || | ||
106 | (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) { | ||
107 | offset += dist_betwn_starts; | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | check if we need to enable the FIFO after the first 4 lines | ||
112 | For the upstream video channel, the risc engine will enable | ||
113 | the FIFO. | ||
114 | */ | ||
115 | if (fifo_enable && line == 3) { | ||
116 | *(rp++) = RISC_WRITECR; | ||
117 | *(rp++) = sram_ch->dma_ctl; | ||
118 | *(rp++) = FLD_VID_FIFO_EN; | ||
119 | *(rp++) = 0x00000001; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | return rp; | ||
124 | } | ||
125 | |||
126 | static int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, | ||
127 | struct pci_dev *pci, | ||
128 | unsigned int top_offset, | ||
129 | unsigned int bpl, | ||
130 | unsigned int lines) | ||
131 | { | ||
132 | __le32 *rp; | ||
133 | int fifo_enable = 0; | ||
134 | int singlefield_lines = lines >> 1; /*get line count for single field */ | ||
135 | int odd_num_lines = singlefield_lines; | ||
136 | int frame = 0; | ||
137 | int frame_size = 0; | ||
138 | int databuf_offset = 0; | ||
139 | int risc_program_size = 0; | ||
140 | int risc_flag = RISC_CNT_RESET; | ||
141 | unsigned int bottom_offset = bpl; | ||
142 | dma_addr_t risc_phys_jump_addr; | ||
143 | |||
144 | if (dev->_isNTSC_ch2) { | ||
145 | odd_num_lines = singlefield_lines + 1; | ||
146 | risc_program_size = FRAME1_VID_PROG_SIZE; | ||
147 | if (bpl == Y411_LINE_SZ) | ||
148 | frame_size = FRAME_SIZE_NTSC_Y411; | ||
149 | else | ||
150 | frame_size = FRAME_SIZE_NTSC_Y422; | ||
151 | } else { | ||
152 | risc_program_size = PAL_VID_PROG_SIZE; | ||
153 | if (bpl == Y411_LINE_SZ) | ||
154 | frame_size = FRAME_SIZE_PAL_Y411; | ||
155 | else | ||
156 | frame_size = FRAME_SIZE_PAL_Y422; | ||
157 | } | ||
158 | |||
159 | /* Virtual address of Risc buffer program */ | ||
160 | rp = dev->_dma_virt_addr_ch2; | ||
161 | |||
162 | for (frame = 0; frame < NUM_FRAMES; frame++) { | ||
163 | databuf_offset = frame_size * frame; | ||
164 | |||
165 | if (UNSET != top_offset) { | ||
166 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | ||
167 | rp = cx25821_risc_field_upstream_ch2(dev, rp, | ||
168 | dev->_data_buf_phys_addr_ch2 + databuf_offset, | ||
169 | top_offset, 0, bpl, odd_num_lines, fifo_enable, | ||
170 | ODD_FIELD); | ||
171 | } | ||
172 | |||
173 | fifo_enable = FIFO_DISABLE; | ||
174 | |||
175 | /* Even field */ | ||
176 | rp = cx25821_risc_field_upstream_ch2(dev, rp, | ||
177 | dev->_data_buf_phys_addr_ch2 + databuf_offset, | ||
178 | bottom_offset, 0x200, bpl, singlefield_lines, | ||
179 | fifo_enable, EVEN_FIELD); | ||
180 | |||
181 | if (frame == 0) { | ||
182 | risc_flag = RISC_CNT_RESET; | ||
183 | risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 + | ||
184 | risc_program_size; | ||
185 | } else { | ||
186 | risc_flag = RISC_CNT_INC; | ||
187 | risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Loop to 2ndFrameRISC or to Start of | ||
192 | * Risc program & generate IRQ | ||
193 | */ | ||
194 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | ||
195 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
196 | *(rp++) = cpu_to_le32(0); | ||
197 | } | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) | ||
203 | { | ||
204 | struct sram_channel *sram_ch = | ||
205 | dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels; | ||
206 | u32 tmp = 0; | ||
207 | |||
208 | if (!dev->_is_running_ch2) { | ||
209 | pr_info("No video file is currently running so return!\n"); | ||
210 | return; | ||
211 | } | ||
212 | /* Disable RISC interrupts */ | ||
213 | tmp = cx_read(sram_ch->int_msk); | ||
214 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); | ||
215 | |||
216 | /* Turn OFF risc and fifo */ | ||
217 | tmp = cx_read(sram_ch->dma_ctl); | ||
218 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); | ||
219 | |||
220 | /* Clear data buffer memory */ | ||
221 | if (dev->_data_buf_virt_addr_ch2) | ||
222 | memset(dev->_data_buf_virt_addr_ch2, 0, | ||
223 | dev->_data_buf_size_ch2); | ||
224 | |||
225 | dev->_is_running_ch2 = 0; | ||
226 | dev->_is_first_frame_ch2 = 0; | ||
227 | dev->_frame_count_ch2 = 0; | ||
228 | dev->_file_status_ch2 = END_OF_FILE; | ||
229 | |||
230 | kfree(dev->_irq_queues_ch2); | ||
231 | dev->_irq_queues_ch2 = NULL; | ||
232 | |||
233 | kfree(dev->_filename_ch2); | ||
234 | |||
235 | tmp = cx_read(VID_CH_MODE_SEL); | ||
236 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | ||
237 | } | ||
238 | |||
239 | void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) | ||
240 | { | ||
241 | if (dev->_is_running_ch2) | ||
242 | cx25821_stop_upstream_video_ch2(dev); | ||
243 | |||
244 | if (dev->_dma_virt_addr_ch2) { | ||
245 | pci_free_consistent(dev->pci, dev->_risc_size_ch2, | ||
246 | dev->_dma_virt_addr_ch2, | ||
247 | dev->_dma_phys_addr_ch2); | ||
248 | dev->_dma_virt_addr_ch2 = NULL; | ||
249 | } | ||
250 | |||
251 | if (dev->_data_buf_virt_addr_ch2) { | ||
252 | pci_free_consistent(dev->pci, dev->_data_buf_size_ch2, | ||
253 | dev->_data_buf_virt_addr_ch2, | ||
254 | dev->_data_buf_phys_addr_ch2); | ||
255 | dev->_data_buf_virt_addr_ch2 = NULL; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | static int cx25821_get_frame_ch2(struct cx25821_dev *dev, | ||
260 | struct sram_channel *sram_ch) | ||
261 | { | ||
262 | struct file *myfile; | ||
263 | int frame_index_temp = dev->_frame_index_ch2; | ||
264 | int i = 0; | ||
265 | int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? | ||
266 | Y411_LINE_SZ : Y422_LINE_SZ; | ||
267 | int frame_size = 0; | ||
268 | int frame_offset = 0; | ||
269 | ssize_t vfs_read_retval = 0; | ||
270 | char mybuf[line_size]; | ||
271 | loff_t file_offset; | ||
272 | loff_t pos; | ||
273 | mm_segment_t old_fs; | ||
274 | |||
275 | if (dev->_file_status_ch2 == END_OF_FILE) | ||
276 | return 0; | ||
277 | |||
278 | if (dev->_isNTSC_ch2) { | ||
279 | frame_size = (line_size == Y411_LINE_SZ) ? | ||
280 | FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; | ||
281 | } else { | ||
282 | frame_size = (line_size == Y411_LINE_SZ) ? | ||
283 | FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
284 | } | ||
285 | |||
286 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | ||
287 | file_offset = dev->_frame_count_ch2 * frame_size; | ||
288 | |||
289 | myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); | ||
290 | if (IS_ERR(myfile)) { | ||
291 | const int open_errno = -PTR_ERR(myfile); | ||
292 | pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", | ||
293 | __func__, dev->_filename_ch2, open_errno); | ||
294 | return PTR_ERR(myfile); | ||
295 | } else { | ||
296 | if (!(myfile->f_op)) { | ||
297 | pr_err("%s(): File has no file operations registered!\n", | ||
298 | __func__); | ||
299 | filp_close(myfile, NULL); | ||
300 | return -EIO; | ||
301 | } | ||
302 | |||
303 | if (!myfile->f_op->read) { | ||
304 | pr_err("%s(): File has no READ operations registered!\n", | ||
305 | __func__); | ||
306 | filp_close(myfile, NULL); | ||
307 | return -EIO; | ||
308 | } | ||
309 | |||
310 | pos = myfile->f_pos; | ||
311 | old_fs = get_fs(); | ||
312 | set_fs(KERNEL_DS); | ||
313 | |||
314 | for (i = 0; i < dev->_lines_count_ch2; i++) { | ||
315 | pos = file_offset; | ||
316 | |||
317 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, | ||
318 | &pos); | ||
319 | |||
320 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | ||
321 | && dev->_data_buf_virt_addr_ch2 != NULL) { | ||
322 | memcpy((void *)(dev->_data_buf_virt_addr_ch2 + | ||
323 | frame_offset / 4), mybuf, | ||
324 | vfs_read_retval); | ||
325 | } | ||
326 | |||
327 | file_offset += vfs_read_retval; | ||
328 | frame_offset += vfs_read_retval; | ||
329 | |||
330 | if (vfs_read_retval < line_size) { | ||
331 | pr_info("Done: exit %s() since no more bytes to read from Video file\n", | ||
332 | __func__); | ||
333 | break; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | if (i > 0) | ||
338 | dev->_frame_count_ch2++; | ||
339 | |||
340 | dev->_file_status_ch2 = (vfs_read_retval == line_size) ? | ||
341 | IN_PROGRESS : END_OF_FILE; | ||
342 | |||
343 | set_fs(old_fs); | ||
344 | filp_close(myfile, NULL); | ||
345 | } | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static void cx25821_vidups_handler_ch2(struct work_struct *work) | ||
351 | { | ||
352 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, | ||
353 | _irq_work_entry_ch2); | ||
354 | |||
355 | if (!dev) { | ||
356 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", | ||
357 | __func__); | ||
358 | return; | ||
359 | } | ||
360 | |||
361 | cx25821_get_frame_ch2(dev, dev->channels[dev-> | ||
362 | _channel2_upstream_select].sram_channels); | ||
363 | } | ||
364 | |||
365 | static int cx25821_openfile_ch2(struct cx25821_dev *dev, | ||
366 | struct sram_channel *sram_ch) | ||
367 | { | ||
368 | struct file *myfile; | ||
369 | int i = 0, j = 0; | ||
370 | int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? | ||
371 | Y411_LINE_SZ : Y422_LINE_SZ; | ||
372 | ssize_t vfs_read_retval = 0; | ||
373 | char mybuf[line_size]; | ||
374 | loff_t pos; | ||
375 | loff_t offset = (unsigned long)0; | ||
376 | mm_segment_t old_fs; | ||
377 | |||
378 | myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); | ||
379 | |||
380 | if (IS_ERR(myfile)) { | ||
381 | const int open_errno = -PTR_ERR(myfile); | ||
382 | pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", | ||
383 | __func__, dev->_filename_ch2, open_errno); | ||
384 | return PTR_ERR(myfile); | ||
385 | } else { | ||
386 | if (!(myfile->f_op)) { | ||
387 | pr_err("%s(): File has no file operations registered!\n", | ||
388 | __func__); | ||
389 | filp_close(myfile, NULL); | ||
390 | return -EIO; | ||
391 | } | ||
392 | |||
393 | if (!myfile->f_op->read) { | ||
394 | pr_err("%s(): File has no READ operations registered! Returning\n", | ||
395 | __func__); | ||
396 | filp_close(myfile, NULL); | ||
397 | return -EIO; | ||
398 | } | ||
399 | |||
400 | pos = myfile->f_pos; | ||
401 | old_fs = get_fs(); | ||
402 | set_fs(KERNEL_DS); | ||
403 | |||
404 | for (j = 0; j < NUM_FRAMES; j++) { | ||
405 | for (i = 0; i < dev->_lines_count_ch2; i++) { | ||
406 | pos = offset; | ||
407 | |||
408 | vfs_read_retval = vfs_read(myfile, mybuf, | ||
409 | line_size, &pos); | ||
410 | |||
411 | if (vfs_read_retval > 0 && | ||
412 | vfs_read_retval == line_size && | ||
413 | dev->_data_buf_virt_addr_ch2 != NULL) { | ||
414 | memcpy((void *)(dev-> | ||
415 | _data_buf_virt_addr_ch2 | ||
416 | + offset / 4), mybuf, | ||
417 | vfs_read_retval); | ||
418 | } | ||
419 | |||
420 | offset += vfs_read_retval; | ||
421 | |||
422 | if (vfs_read_retval < line_size) { | ||
423 | pr_info("Done: exit %s() since no more bytes to read from Video file\n", | ||
424 | __func__); | ||
425 | break; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | if (i > 0) | ||
430 | dev->_frame_count_ch2++; | ||
431 | |||
432 | if (vfs_read_retval < line_size) | ||
433 | break; | ||
434 | } | ||
435 | |||
436 | dev->_file_status_ch2 = (vfs_read_retval == line_size) ? | ||
437 | IN_PROGRESS : END_OF_FILE; | ||
438 | |||
439 | set_fs(old_fs); | ||
440 | myfile->f_pos = 0; | ||
441 | filp_close(myfile, NULL); | ||
442 | } | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, | ||
448 | struct sram_channel *sram_ch, | ||
449 | int bpl) | ||
450 | { | ||
451 | int ret = 0; | ||
452 | dma_addr_t dma_addr; | ||
453 | dma_addr_t data_dma_addr; | ||
454 | |||
455 | if (dev->_dma_virt_addr_ch2 != NULL) { | ||
456 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, | ||
457 | dev->_dma_virt_addr_ch2, | ||
458 | dev->_dma_phys_addr_ch2); | ||
459 | } | ||
460 | |||
461 | dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, | ||
462 | dev->upstream_riscbuf_size_ch2, &dma_addr); | ||
463 | dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; | ||
464 | dev->_dma_phys_start_addr_ch2 = dma_addr; | ||
465 | dev->_dma_phys_addr_ch2 = dma_addr; | ||
466 | dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2; | ||
467 | |||
468 | if (!dev->_dma_virt_addr_ch2) { | ||
469 | pr_err("FAILED to allocate memory for Risc buffer! Returning\n"); | ||
470 | return -ENOMEM; | ||
471 | } | ||
472 | |||
473 | /* Iniitize at this address until n bytes to 0 */ | ||
474 | memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2); | ||
475 | |||
476 | if (dev->_data_buf_virt_addr_ch2 != NULL) { | ||
477 | pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2, | ||
478 | dev->_data_buf_virt_addr_ch2, | ||
479 | dev->_data_buf_phys_addr_ch2); | ||
480 | } | ||
481 | /* For Video Data buffer allocation */ | ||
482 | dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, | ||
483 | dev->upstream_databuf_size_ch2, &data_dma_addr); | ||
484 | dev->_data_buf_phys_addr_ch2 = data_dma_addr; | ||
485 | dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; | ||
486 | |||
487 | if (!dev->_data_buf_virt_addr_ch2) { | ||
488 | pr_err("FAILED to allocate memory for data buffer! Returning\n"); | ||
489 | return -ENOMEM; | ||
490 | } | ||
491 | |||
492 | /* Initialize at this address until n bytes to 0 */ | ||
493 | memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2); | ||
494 | |||
495 | ret = cx25821_openfile_ch2(dev, sram_ch); | ||
496 | if (ret < 0) | ||
497 | return ret; | ||
498 | |||
499 | /* Creating RISC programs */ | ||
500 | ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, | ||
501 | dev->_lines_count_ch2); | ||
502 | if (ret < 0) { | ||
503 | pr_info("Failed creating Video Upstream Risc programs!\n"); | ||
504 | goto error; | ||
505 | } | ||
506 | |||
507 | return 0; | ||
508 | |||
509 | error: | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | static int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, | ||
514 | int chan_num, | ||
515 | u32 status) | ||
516 | { | ||
517 | u32 int_msk_tmp; | ||
518 | struct sram_channel *channel = dev->channels[chan_num].sram_channels; | ||
519 | int singlefield_lines = NTSC_FIELD_HEIGHT; | ||
520 | int line_size_in_bytes = Y422_LINE_SZ; | ||
521 | int odd_risc_prog_size = 0; | ||
522 | dma_addr_t risc_phys_jump_addr; | ||
523 | __le32 *rp; | ||
524 | |||
525 | if (status & FLD_VID_SRC_RISC1) { | ||
526 | /* We should only process one program per call */ | ||
527 | u32 prog_cnt = cx_read(channel->gpcnt); | ||
528 | |||
529 | /* | ||
530 | * Since we've identified our IRQ, clear our bits from the | ||
531 | * interrupt mask and interrupt status registers | ||
532 | */ | ||
533 | int_msk_tmp = cx_read(channel->int_msk); | ||
534 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | ||
535 | cx_write(channel->int_stat, _intr_msk); | ||
536 | |||
537 | spin_lock(&dev->slock); | ||
538 | |||
539 | dev->_frame_index_ch2 = prog_cnt; | ||
540 | |||
541 | queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2); | ||
542 | |||
543 | if (dev->_is_first_frame_ch2) { | ||
544 | dev->_is_first_frame_ch2 = 0; | ||
545 | |||
546 | if (dev->_isNTSC_ch2) { | ||
547 | singlefield_lines += 1; | ||
548 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; | ||
549 | } else { | ||
550 | singlefield_lines = PAL_FIELD_HEIGHT; | ||
551 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; | ||
552 | } | ||
553 | |||
554 | if (dev->_dma_virt_start_addr_ch2 != NULL) { | ||
555 | if (dev->_pixel_format_ch2 == PIXEL_FRMT_411) | ||
556 | line_size_in_bytes = Y411_LINE_SZ; | ||
557 | else | ||
558 | line_size_in_bytes = Y422_LINE_SZ; | ||
559 | risc_phys_jump_addr = | ||
560 | dev->_dma_phys_start_addr_ch2 + | ||
561 | odd_risc_prog_size; | ||
562 | |||
563 | rp = cx25821_update_riscprogram_ch2(dev, | ||
564 | dev->_dma_virt_start_addr_ch2, | ||
565 | TOP_OFFSET, line_size_in_bytes, | ||
566 | 0x0, singlefield_lines, | ||
567 | FIFO_DISABLE, ODD_FIELD); | ||
568 | |||
569 | /* Jump to Even Risc program of 1st Frame */ | ||
570 | *(rp++) = cpu_to_le32(RISC_JUMP); | ||
571 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | ||
572 | *(rp++) = cpu_to_le32(0); | ||
573 | } | ||
574 | } | ||
575 | |||
576 | spin_unlock(&dev->slock); | ||
577 | } | ||
578 | |||
579 | if (dev->_file_status_ch2 == END_OF_FILE) { | ||
580 | pr_info("EOF Channel 2 Framecount = %d\n", | ||
581 | dev->_frame_count_ch2); | ||
582 | return -1; | ||
583 | } | ||
584 | /* ElSE, set the interrupt mask register, re-enable irq. */ | ||
585 | int_msk_tmp = cx_read(channel->int_msk); | ||
586 | cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) | ||
592 | { | ||
593 | struct cx25821_dev *dev = dev_id; | ||
594 | u32 vid_status; | ||
595 | int handled = 0; | ||
596 | int channel_num = 0; | ||
597 | struct sram_channel *sram_ch; | ||
598 | |||
599 | if (!dev) | ||
600 | return -1; | ||
601 | |||
602 | channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; | ||
603 | sram_ch = dev->channels[channel_num].sram_channels; | ||
604 | |||
605 | vid_status = cx_read(sram_ch->int_stat); | ||
606 | |||
607 | /* Only deal with our interrupt */ | ||
608 | if (vid_status) | ||
609 | handled = cx25821_video_upstream_irq_ch2(dev, channel_num, | ||
610 | vid_status); | ||
611 | |||
612 | if (handled < 0) | ||
613 | cx25821_stop_upstream_video_ch2(dev); | ||
614 | else | ||
615 | handled += handled; | ||
616 | |||
617 | return IRQ_RETVAL(handled); | ||
618 | } | ||
619 | |||
620 | static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, | ||
621 | struct sram_channel *ch, int pix_format) | ||
622 | { | ||
623 | int width = WIDTH_D1; | ||
624 | int height = dev->_lines_count_ch2; | ||
625 | int num_lines, odd_num_lines; | ||
626 | u32 value; | ||
627 | int vip_mode = PIXEL_ENGINE_VIP1; | ||
628 | |||
629 | value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); | ||
630 | value &= 0xFFFFFFEF; | ||
631 | value |= dev->_isNTSC_ch2 ? 0 : 0x10; | ||
632 | cx_write(ch->vid_fmt_ctl, value); | ||
633 | |||
634 | /* | ||
635 | * set number of active pixels in each line. Default is 720 | ||
636 | * pixels in both NTSC and PAL format | ||
637 | */ | ||
638 | cx_write(ch->vid_active_ctl1, width); | ||
639 | |||
640 | num_lines = (height / 2) & 0x3FF; | ||
641 | odd_num_lines = num_lines; | ||
642 | |||
643 | if (dev->_isNTSC_ch2) | ||
644 | odd_num_lines += 1; | ||
645 | |||
646 | value = (num_lines << 16) | odd_num_lines; | ||
647 | |||
648 | /* set number of active lines in field 0 (top) and field 1 (bottom) */ | ||
649 | cx_write(ch->vid_active_ctl2, value); | ||
650 | |||
651 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); | ||
652 | } | ||
653 | |||
654 | static int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, | ||
655 | struct sram_channel *sram_ch) | ||
656 | { | ||
657 | u32 tmp = 0; | ||
658 | int err = 0; | ||
659 | |||
660 | /* | ||
661 | * 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface | ||
662 | * for channel A-C | ||
663 | */ | ||
664 | tmp = cx_read(VID_CH_MODE_SEL); | ||
665 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
666 | |||
667 | /* | ||
668 | * Set the physical start address of the RISC program in the initial | ||
669 | * program counter(IPC) member of the cmds. | ||
670 | */ | ||
671 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); | ||
672 | cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ | ||
673 | |||
674 | /* reset counter */ | ||
675 | cx_write(sram_ch->gpcnt_ctl, 3); | ||
676 | |||
677 | /* Clear our bits from the interrupt status register. */ | ||
678 | cx_write(sram_ch->int_stat, _intr_msk); | ||
679 | |||
680 | /* Set the interrupt mask register, enable irq. */ | ||
681 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); | ||
682 | tmp = cx_read(sram_ch->int_msk); | ||
683 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | ||
684 | |||
685 | err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, | ||
686 | IRQF_SHARED, dev->name, dev); | ||
687 | if (err < 0) { | ||
688 | pr_err("%s: can't get upstream IRQ %d\n", | ||
689 | dev->name, dev->pci->irq); | ||
690 | goto fail_irq; | ||
691 | } | ||
692 | /* Start the DMA engine */ | ||
693 | tmp = cx_read(sram_ch->dma_ctl); | ||
694 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); | ||
695 | |||
696 | dev->_is_running_ch2 = 1; | ||
697 | dev->_is_first_frame_ch2 = 1; | ||
698 | |||
699 | return 0; | ||
700 | |||
701 | fail_irq: | ||
702 | cx25821_dev_unregister(dev); | ||
703 | return err; | ||
704 | } | ||
705 | |||
706 | int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, | ||
707 | int pixel_format) | ||
708 | { | ||
709 | struct sram_channel *sram_ch; | ||
710 | u32 tmp; | ||
711 | int err = 0; | ||
712 | int data_frame_size = 0; | ||
713 | int risc_buffer_size = 0; | ||
714 | |||
715 | if (dev->_is_running_ch2) { | ||
716 | pr_info("Video Channel is still running so return!\n"); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | dev->_channel2_upstream_select = channel_select; | ||
721 | sram_ch = dev->channels[channel_select].sram_channels; | ||
722 | |||
723 | INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); | ||
724 | dev->_irq_queues_ch2 = | ||
725 | create_singlethread_workqueue("cx25821_workqueue2"); | ||
726 | |||
727 | if (!dev->_irq_queues_ch2) { | ||
728 | pr_err("create_singlethread_workqueue() for Video FAILED!\n"); | ||
729 | return -ENOMEM; | ||
730 | } | ||
731 | /* | ||
732 | * 656/VIP SRC Upstream Channel I & J and 7 - | ||
733 | * Host Bus Interface for channel A-C | ||
734 | */ | ||
735 | tmp = cx_read(VID_CH_MODE_SEL); | ||
736 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | ||
737 | |||
738 | dev->_is_running_ch2 = 0; | ||
739 | dev->_frame_count_ch2 = 0; | ||
740 | dev->_file_status_ch2 = RESET_STATUS; | ||
741 | dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; | ||
742 | dev->_pixel_format_ch2 = pixel_format; | ||
743 | dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? | ||
744 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
745 | data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | ||
746 | risc_buffer_size = dev->_isNTSC_ch2 ? | ||
747 | NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | ||
748 | |||
749 | if (dev->input_filename_ch2) | ||
750 | dev->_filename_ch2 = kstrdup(dev->input_filename_ch2, | ||
751 | GFP_KERNEL); | ||
752 | else | ||
753 | dev->_filename_ch2 = kstrdup(dev->_defaultname_ch2, | ||
754 | GFP_KERNEL); | ||
755 | |||
756 | if (!dev->_filename_ch2) { | ||
757 | err = -ENOENT; | ||
758 | goto error; | ||
759 | } | ||
760 | |||
761 | /* Default if filename is empty string */ | ||
762 | if (strcmp(dev->_filename_ch2, "") == 0) { | ||
763 | if (dev->_isNTSC_ch2) { | ||
764 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == | ||
765 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : | ||
766 | "/root/vidtest.yuv"; | ||
767 | } else { | ||
768 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == | ||
769 | PIXEL_FRMT_411) ? "/root/pal411.yuv" : | ||
770 | "/root/pal422.yuv"; | ||
771 | } | ||
772 | } | ||
773 | |||
774 | err = cx25821_sram_channel_setup_upstream(dev, sram_ch, | ||
775 | dev->_line_size_ch2, 0); | ||
776 | |||
777 | /* setup fifo + format */ | ||
778 | cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2); | ||
779 | |||
780 | dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; | ||
781 | dev->upstream_databuf_size_ch2 = data_frame_size * 2; | ||
782 | |||
783 | /* Allocating buffers and prepare RISC program */ | ||
784 | err = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, | ||
785 | dev->_line_size_ch2); | ||
786 | if (err < 0) { | ||
787 | pr_err("%s: Failed to set up Video upstream buffers!\n", | ||
788 | dev->name); | ||
789 | goto error; | ||
790 | } | ||
791 | |||
792 | cx25821_start_video_dma_upstream_ch2(dev, sram_ch); | ||
793 | |||
794 | return 0; | ||
795 | |||
796 | error: | ||
797 | cx25821_dev_unregister(dev); | ||
798 | |||
799 | return err; | ||
800 | } | ||
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h deleted file mode 100644 index d42dab59b663..000000000000 --- a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h +++ /dev/null | |||
@@ -1,138 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for the Conexant CX25821 PCIe bridge | ||
3 | * | ||
4 | * Copyright (C) 2009 Conexant Systems Inc. | ||
5 | * Authors <hiep.huynh@conexant.com>, <shu.lin@conexant.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/workqueue.h> | ||
25 | |||
26 | #define OPEN_FILE_1 0 | ||
27 | #define NUM_PROGS 8 | ||
28 | #define NUM_FRAMES 2 | ||
29 | #define ODD_FIELD 0 | ||
30 | #define EVEN_FIELD 1 | ||
31 | #define TOP_OFFSET 0 | ||
32 | #define FIFO_DISABLE 0 | ||
33 | #define FIFO_ENABLE 1 | ||
34 | #define TEST_FRAMES 5 | ||
35 | #define END_OF_FILE 0 | ||
36 | #define IN_PROGRESS 1 | ||
37 | #define RESET_STATUS -1 | ||
38 | #define NUM_NO_OPS 5 | ||
39 | |||
40 | /* PAL and NTSC line sizes and number of lines. */ | ||
41 | #define WIDTH_D1 720 | ||
42 | #define NTSC_LINES_PER_FRAME 480 | ||
43 | #define PAL_LINES_PER_FRAME 576 | ||
44 | #define PAL_LINE_SZ 1440 | ||
45 | #define Y422_LINE_SZ 1440 | ||
46 | #define Y411_LINE_SZ 1080 | ||
47 | #define NTSC_FIELD_HEIGHT 240 | ||
48 | #define NTSC_ODD_FLD_LINES 241 | ||
49 | #define PAL_FIELD_HEIGHT 288 | ||
50 | |||
51 | #define FRAME_SIZE_NTSC_Y422 (NTSC_LINES_PER_FRAME * Y422_LINE_SZ) | ||
52 | #define FRAME_SIZE_NTSC_Y411 (NTSC_LINES_PER_FRAME * Y411_LINE_SZ) | ||
53 | #define FRAME_SIZE_PAL_Y422 (PAL_LINES_PER_FRAME * Y422_LINE_SZ) | ||
54 | #define FRAME_SIZE_PAL_Y411 (PAL_LINES_PER_FRAME * Y411_LINE_SZ) | ||
55 | |||
56 | #define NTSC_DATA_BUF_SZ (Y422_LINE_SZ * NTSC_LINES_PER_FRAME) | ||
57 | #define PAL_DATA_BUF_SZ (Y422_LINE_SZ * PAL_LINES_PER_FRAME) | ||
58 | |||
59 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | ||
60 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | ||
61 | #define JUMP_INSTRUCTION_SIZE 12 | ||
62 | #define MAXSIZE_NO_OPS 36 | ||
63 | #define DWORD_SIZE 4 | ||
64 | |||
65 | #define USE_RISC_NOOP_VIDEO 1 | ||
66 | |||
67 | #ifdef USE_RISC_NOOP_VIDEO | ||
68 | #define PAL_US_VID_PROG_SIZE \ | ||
69 | (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ | ||
70 | RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE + \ | ||
71 | NUM_NO_OPS * DWORD_SIZE) | ||
72 | |||
73 | #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) | ||
74 | |||
75 | #define PAL_VID_PROG_SIZE \ | ||
76 | ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE + \ | ||
77 | 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
78 | JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE) | ||
79 | |||
80 | #define ODD_FLD_PAL_PROG_SIZE \ | ||
81 | (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ | ||
82 | RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
83 | NUM_NO_OPS * DWORD_SIZE) | ||
84 | |||
85 | #define NTSC_US_VID_PROG_SIZE \ | ||
86 | ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + \ | ||
87 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + \ | ||
88 | NUM_NO_OPS * DWORD_SIZE) | ||
89 | |||
90 | #define NTSC_RISC_BUF_SIZE \ | ||
91 | (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) | ||
92 | |||
93 | #define FRAME1_VID_PROG_SIZE \ | ||
94 | ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * \ | ||
95 | 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE + \ | ||
96 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE + \ | ||
97 | 2 * NUM_NO_OPS * DWORD_SIZE) | ||
98 | |||
99 | #define ODD_FLD_NTSC_PROG_SIZE \ | ||
100 | (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE + \ | ||
101 | RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
102 | NUM_NO_OPS * DWORD_SIZE) | ||
103 | #endif | ||
104 | |||
105 | #ifndef USE_RISC_NOOP_VIDEO | ||
106 | #define PAL_US_VID_PROG_SIZE \ | ||
107 | ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + \ | ||
108 | RISC_WRITECR_INSTRUCTION_SIZE) | ||
109 | |||
110 | #define PAL_RISC_BUF_SIZE \ | ||
111 | (2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE)) | ||
112 | |||
113 | #define PAL_VID_PROG_SIZE \ | ||
114 | ((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE + \ | ||
115 | 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \ | ||
116 | JUMP_INSTRUCTION_SIZE) | ||
117 | |||
118 | #define ODD_FLD_PAL_PROG_SIZE \ | ||
119 | (PAL_FIELD_HEIGHT * 3 * DWORD_SIZE + \ | ||
120 | RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) | ||
121 | |||
122 | #define ODD_FLD_NTSC_PROG_SIZE \ | ||
123 | (NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE + \ | ||
124 | RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) | ||
125 | |||
126 | #define NTSC_US_VID_PROG_SIZE \ | ||
127 | ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + \ | ||
128 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
129 | |||
130 | #define NTSC_RISC_BUF_SIZE \ | ||
131 | (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) | ||
132 | |||
133 | #define FRAME1_VID_PROG_SIZE \ | ||
134 | ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * \ | ||
135 | 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE + \ | ||
136 | RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) | ||
137 | |||
138 | #endif | ||
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c index 7fc97110d973..88ffef410c50 100644 --- a/drivers/media/pci/cx25821/cx25821-video-upstream.c +++ b/drivers/media/pci/cx25821/cx25821-video-upstream.c | |||
@@ -25,16 +25,11 @@ | |||
25 | #include "cx25821-video.h" | 25 | #include "cx25821-video.h" |
26 | #include "cx25821-video-upstream.h" | 26 | #include "cx25821-video-upstream.h" |
27 | 27 | ||
28 | #include <linux/fs.h> | ||
29 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
30 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
31 | #include <linux/init.h> | 30 | #include <linux/init.h> |
32 | #include <linux/module.h> | 31 | #include <linux/module.h> |
33 | #include <linux/syscalls.h> | ||
34 | #include <linux/file.h> | ||
35 | #include <linux/fcntl.h> | ||
36 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
37 | #include <linux/uaccess.h> | ||
38 | 33 | ||
39 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | 34 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); |
40 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | 35 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); |
@@ -44,7 +39,7 @@ static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | | |||
44 | FLD_VID_SRC_OPC_ERR; | 39 | FLD_VID_SRC_OPC_ERR; |
45 | 40 | ||
46 | int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | 41 | int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, |
47 | struct sram_channel *ch, | 42 | const struct sram_channel *ch, |
48 | unsigned int bpl, u32 risc) | 43 | unsigned int bpl, u32 risc) |
49 | { | 44 | { |
50 | unsigned int i, lines; | 45 | unsigned int i, lines; |
@@ -97,12 +92,13 @@ int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | |||
97 | return 0; | 92 | return 0; |
98 | } | 93 | } |
99 | 94 | ||
100 | static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, | 95 | static __le32 *cx25821_update_riscprogram(struct cx25821_channel *chan, |
101 | __le32 *rp, unsigned int offset, | 96 | __le32 *rp, unsigned int offset, |
102 | unsigned int bpl, u32 sync_line, | 97 | unsigned int bpl, u32 sync_line, |
103 | unsigned int lines, int fifo_enable, | 98 | unsigned int lines, int fifo_enable, |
104 | int field_type) | 99 | int field_type) |
105 | { | 100 | { |
101 | struct cx25821_video_out_data *out = chan->out; | ||
106 | unsigned int line, i; | 102 | unsigned int line, i; |
107 | int dist_betwn_starts = bpl * 2; | 103 | int dist_betwn_starts = bpl * 2; |
108 | 104 | ||
@@ -116,11 +112,11 @@ static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, | |||
116 | /* scan lines */ | 112 | /* scan lines */ |
117 | for (line = 0; line < lines; line++) { | 113 | for (line = 0; line < lines; line++) { |
118 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); | 114 | *(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl); |
119 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset); | 115 | *(rp++) = cpu_to_le32(out->_data_buf_phys_addr + offset); |
120 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 116 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
121 | 117 | ||
122 | if ((lines <= NTSC_FIELD_HEIGHT) | 118 | if ((lines <= NTSC_FIELD_HEIGHT) |
123 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) { | 119 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(out->is_60hz)) { |
124 | offset += dist_betwn_starts; | 120 | offset += dist_betwn_starts; |
125 | } | 121 | } |
126 | } | 122 | } |
@@ -128,15 +124,15 @@ static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev, | |||
128 | return rp; | 124 | return rp; |
129 | } | 125 | } |
130 | 126 | ||
131 | static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | 127 | static __le32 *cx25821_risc_field_upstream(struct cx25821_channel *chan, __le32 *rp, |
132 | dma_addr_t databuf_phys_addr, | 128 | dma_addr_t databuf_phys_addr, |
133 | unsigned int offset, u32 sync_line, | 129 | unsigned int offset, u32 sync_line, |
134 | unsigned int bpl, unsigned int lines, | 130 | unsigned int bpl, unsigned int lines, |
135 | int fifo_enable, int field_type) | 131 | int fifo_enable, int field_type) |
136 | { | 132 | { |
133 | struct cx25821_video_out_data *out = chan->out; | ||
137 | unsigned int line, i; | 134 | unsigned int line, i; |
138 | struct sram_channel *sram_ch = | 135 | const struct sram_channel *sram_ch = chan->sram_channels; |
139 | dev->channels[dev->_channel_upstream_select].sram_channels; | ||
140 | int dist_betwn_starts = bpl * 2; | 136 | int dist_betwn_starts = bpl * 2; |
141 | 137 | ||
142 | /* sync instruction */ | 138 | /* sync instruction */ |
@@ -155,7 +151,7 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | |||
155 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 151 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
156 | 152 | ||
157 | if ((lines <= NTSC_FIELD_HEIGHT) | 153 | if ((lines <= NTSC_FIELD_HEIGHT) |
158 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) | 154 | || (line < (NTSC_FIELD_HEIGHT - 1)) || !(out->is_60hz)) |
159 | /* to skip the other field line */ | 155 | /* to skip the other field line */ |
160 | offset += dist_betwn_starts; | 156 | offset += dist_betwn_starts; |
161 | 157 | ||
@@ -173,11 +169,12 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | |||
173 | return rp; | 169 | return rp; |
174 | } | 170 | } |
175 | 171 | ||
176 | static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | 172 | static int cx25821_risc_buffer_upstream(struct cx25821_channel *chan, |
177 | struct pci_dev *pci, | 173 | struct pci_dev *pci, |
178 | unsigned int top_offset, | 174 | unsigned int top_offset, |
179 | unsigned int bpl, unsigned int lines) | 175 | unsigned int bpl, unsigned int lines) |
180 | { | 176 | { |
177 | struct cx25821_video_out_data *out = chan->out; | ||
181 | __le32 *rp; | 178 | __le32 *rp; |
182 | int fifo_enable = 0; | 179 | int fifo_enable = 0; |
183 | /* get line count for single field */ | 180 | /* get line count for single field */ |
@@ -191,7 +188,7 @@ static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
191 | unsigned int bottom_offset = bpl; | 188 | unsigned int bottom_offset = bpl; |
192 | dma_addr_t risc_phys_jump_addr; | 189 | dma_addr_t risc_phys_jump_addr; |
193 | 190 | ||
194 | if (dev->_isNTSC) { | 191 | if (out->is_60hz) { |
195 | odd_num_lines = singlefield_lines + 1; | 192 | odd_num_lines = singlefield_lines + 1; |
196 | risc_program_size = FRAME1_VID_PROG_SIZE; | 193 | risc_program_size = FRAME1_VID_PROG_SIZE; |
197 | frame_size = (bpl == Y411_LINE_SZ) ? | 194 | frame_size = (bpl == Y411_LINE_SZ) ? |
@@ -203,15 +200,15 @@ static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
203 | } | 200 | } |
204 | 201 | ||
205 | /* Virtual address of Risc buffer program */ | 202 | /* Virtual address of Risc buffer program */ |
206 | rp = dev->_dma_virt_addr; | 203 | rp = out->_dma_virt_addr; |
207 | 204 | ||
208 | for (frame = 0; frame < NUM_FRAMES; frame++) { | 205 | for (frame = 0; frame < NUM_FRAMES; frame++) { |
209 | databuf_offset = frame_size * frame; | 206 | databuf_offset = frame_size * frame; |
210 | 207 | ||
211 | if (UNSET != top_offset) { | 208 | if (UNSET != top_offset) { |
212 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | 209 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; |
213 | rp = cx25821_risc_field_upstream(dev, rp, | 210 | rp = cx25821_risc_field_upstream(chan, rp, |
214 | dev->_data_buf_phys_addr + | 211 | out->_data_buf_phys_addr + |
215 | databuf_offset, top_offset, 0, bpl, | 212 | databuf_offset, top_offset, 0, bpl, |
216 | odd_num_lines, fifo_enable, ODD_FIELD); | 213 | odd_num_lines, fifo_enable, ODD_FIELD); |
217 | } | 214 | } |
@@ -219,18 +216,18 @@ static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
219 | fifo_enable = FIFO_DISABLE; | 216 | fifo_enable = FIFO_DISABLE; |
220 | 217 | ||
221 | /* Even Field */ | 218 | /* Even Field */ |
222 | rp = cx25821_risc_field_upstream(dev, rp, | 219 | rp = cx25821_risc_field_upstream(chan, rp, |
223 | dev->_data_buf_phys_addr + | 220 | out->_data_buf_phys_addr + |
224 | databuf_offset, bottom_offset, | 221 | databuf_offset, bottom_offset, |
225 | 0x200, bpl, singlefield_lines, | 222 | 0x200, bpl, singlefield_lines, |
226 | fifo_enable, EVEN_FIELD); | 223 | fifo_enable, EVEN_FIELD); |
227 | 224 | ||
228 | if (frame == 0) { | 225 | if (frame == 0) { |
229 | risc_flag = RISC_CNT_RESET; | 226 | risc_flag = RISC_CNT_RESET; |
230 | risc_phys_jump_addr = dev->_dma_phys_start_addr + | 227 | risc_phys_jump_addr = out->_dma_phys_start_addr + |
231 | risc_program_size; | 228 | risc_program_size; |
232 | } else { | 229 | } else { |
233 | risc_phys_jump_addr = dev->_dma_phys_start_addr; | 230 | risc_phys_jump_addr = out->_dma_phys_start_addr; |
234 | risc_flag = RISC_CNT_INC; | 231 | risc_flag = RISC_CNT_INC; |
235 | } | 232 | } |
236 | 233 | ||
@@ -245,16 +242,21 @@ static int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
245 | return 0; | 242 | return 0; |
246 | } | 243 | } |
247 | 244 | ||
248 | void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | 245 | void cx25821_stop_upstream_video(struct cx25821_channel *chan) |
249 | { | 246 | { |
250 | struct sram_channel *sram_ch = | 247 | struct cx25821_video_out_data *out = chan->out; |
251 | dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels; | 248 | struct cx25821_dev *dev = chan->dev; |
249 | const struct sram_channel *sram_ch = chan->sram_channels; | ||
252 | u32 tmp = 0; | 250 | u32 tmp = 0; |
253 | 251 | ||
254 | if (!dev->_is_running) { | 252 | if (!out->_is_running) { |
255 | pr_info("No video file is currently running so return!\n"); | 253 | pr_info("No video file is currently running so return!\n"); |
256 | return; | 254 | return; |
257 | } | 255 | } |
256 | |||
257 | /* Set the interrupt mask register, disable irq. */ | ||
258 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) & ~(1 << sram_ch->irq_bit)); | ||
259 | |||
258 | /* Disable RISC interrupts */ | 260 | /* Disable RISC interrupts */ |
259 | tmp = cx_read(sram_ch->int_msk); | 261 | tmp = cx_read(sram_ch->int_msk); |
260 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); | 262 | cx_write(sram_ch->int_msk, tmp & ~_intr_msk); |
@@ -263,283 +265,133 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | |||
263 | tmp = cx_read(sram_ch->dma_ctl); | 265 | tmp = cx_read(sram_ch->dma_ctl); |
264 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); | 266 | cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); |
265 | 267 | ||
266 | /* Clear data buffer memory */ | 268 | free_irq(dev->pci->irq, chan); |
267 | if (dev->_data_buf_virt_addr) | ||
268 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); | ||
269 | 269 | ||
270 | dev->_is_running = 0; | 270 | /* Clear data buffer memory */ |
271 | dev->_is_first_frame = 0; | 271 | if (out->_data_buf_virt_addr) |
272 | dev->_frame_count = 0; | 272 | memset(out->_data_buf_virt_addr, 0, out->_data_buf_size); |
273 | dev->_file_status = END_OF_FILE; | ||
274 | |||
275 | kfree(dev->_irq_queues); | ||
276 | dev->_irq_queues = NULL; | ||
277 | 273 | ||
278 | kfree(dev->_filename); | 274 | out->_is_running = 0; |
275 | out->_is_first_frame = 0; | ||
276 | out->_frame_count = 0; | ||
277 | out->_file_status = END_OF_FILE; | ||
279 | 278 | ||
280 | tmp = cx_read(VID_CH_MODE_SEL); | 279 | tmp = cx_read(VID_CH_MODE_SEL); |
281 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | 280 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); |
282 | } | 281 | } |
283 | 282 | ||
284 | void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev) | 283 | void cx25821_free_mem_upstream(struct cx25821_channel *chan) |
285 | { | 284 | { |
286 | if (dev->_is_running) | 285 | struct cx25821_video_out_data *out = chan->out; |
287 | cx25821_stop_upstream_video_ch1(dev); | 286 | struct cx25821_dev *dev = chan->dev; |
288 | 287 | ||
289 | if (dev->_dma_virt_addr) { | 288 | if (out->_is_running) |
290 | pci_free_consistent(dev->pci, dev->_risc_size, | 289 | cx25821_stop_upstream_video(chan); |
291 | dev->_dma_virt_addr, dev->_dma_phys_addr); | 290 | |
292 | dev->_dma_virt_addr = NULL; | 291 | if (out->_dma_virt_addr) { |
292 | pci_free_consistent(dev->pci, out->_risc_size, | ||
293 | out->_dma_virt_addr, out->_dma_phys_addr); | ||
294 | out->_dma_virt_addr = NULL; | ||
293 | } | 295 | } |
294 | 296 | ||
295 | if (dev->_data_buf_virt_addr) { | 297 | if (out->_data_buf_virt_addr) { |
296 | pci_free_consistent(dev->pci, dev->_data_buf_size, | 298 | pci_free_consistent(dev->pci, out->_data_buf_size, |
297 | dev->_data_buf_virt_addr, | 299 | out->_data_buf_virt_addr, |
298 | dev->_data_buf_phys_addr); | 300 | out->_data_buf_phys_addr); |
299 | dev->_data_buf_virt_addr = NULL; | 301 | out->_data_buf_virt_addr = NULL; |
300 | } | 302 | } |
301 | } | 303 | } |
302 | 304 | ||
303 | static int cx25821_get_frame(struct cx25821_dev *dev, | 305 | int cx25821_write_frame(struct cx25821_channel *chan, |
304 | struct sram_channel *sram_ch) | 306 | const char __user *data, size_t count) |
305 | { | 307 | { |
306 | struct file *myfile; | 308 | struct cx25821_video_out_data *out = chan->out; |
307 | int frame_index_temp = dev->_frame_index; | 309 | int line_size = (out->_pixel_format == PIXEL_FRMT_411) ? |
308 | int i = 0; | ||
309 | int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? | ||
310 | Y411_LINE_SZ : Y422_LINE_SZ; | 310 | Y411_LINE_SZ : Y422_LINE_SZ; |
311 | int frame_size = 0; | 311 | int frame_size = 0; |
312 | int frame_offset = 0; | 312 | int frame_offset = 0; |
313 | ssize_t vfs_read_retval = 0; | 313 | int curpos = out->curpos; |
314 | char mybuf[line_size]; | ||
315 | loff_t file_offset; | ||
316 | loff_t pos; | ||
317 | mm_segment_t old_fs; | ||
318 | |||
319 | if (dev->_file_status == END_OF_FILE) | ||
320 | return 0; | ||
321 | 314 | ||
322 | if (dev->_isNTSC) | 315 | if (out->is_60hz) |
323 | frame_size = (line_size == Y411_LINE_SZ) ? | 316 | frame_size = (line_size == Y411_LINE_SZ) ? |
324 | FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; | 317 | FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; |
325 | else | 318 | else |
326 | frame_size = (line_size == Y411_LINE_SZ) ? | 319 | frame_size = (line_size == Y411_LINE_SZ) ? |
327 | FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | 320 | FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; |
328 | 321 | ||
329 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | 322 | if (curpos == 0) { |
330 | file_offset = dev->_frame_count * frame_size; | 323 | out->cur_frame_index = out->_frame_index; |
331 | 324 | if (wait_event_interruptible(out->waitq, out->cur_frame_index != out->_frame_index)) | |
332 | myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0); | 325 | return -EINTR; |
333 | 326 | out->cur_frame_index = out->_frame_index; | |
334 | if (IS_ERR(myfile)) { | ||
335 | const int open_errno = -PTR_ERR(myfile); | ||
336 | pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", | ||
337 | __func__, dev->_filename, open_errno); | ||
338 | return PTR_ERR(myfile); | ||
339 | } else { | ||
340 | if (!(myfile->f_op)) { | ||
341 | pr_err("%s(): File has no file operations registered!\n", | ||
342 | __func__); | ||
343 | filp_close(myfile, NULL); | ||
344 | return -EIO; | ||
345 | } | ||
346 | |||
347 | if (!myfile->f_op->read) { | ||
348 | pr_err("%s(): File has no READ operations registered!\n", | ||
349 | __func__); | ||
350 | filp_close(myfile, NULL); | ||
351 | return -EIO; | ||
352 | } | ||
353 | |||
354 | pos = myfile->f_pos; | ||
355 | old_fs = get_fs(); | ||
356 | set_fs(KERNEL_DS); | ||
357 | |||
358 | for (i = 0; i < dev->_lines_count; i++) { | ||
359 | pos = file_offset; | ||
360 | |||
361 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, | ||
362 | &pos); | ||
363 | |||
364 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | ||
365 | && dev->_data_buf_virt_addr != NULL) { | ||
366 | memcpy((void *)(dev->_data_buf_virt_addr + | ||
367 | frame_offset / 4), mybuf, | ||
368 | vfs_read_retval); | ||
369 | } | ||
370 | |||
371 | file_offset += vfs_read_retval; | ||
372 | frame_offset += vfs_read_retval; | ||
373 | |||
374 | if (vfs_read_retval < line_size) { | ||
375 | pr_info("Done: exit %s() since no more bytes to read from Video file\n", | ||
376 | __func__); | ||
377 | break; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | if (i > 0) | ||
382 | dev->_frame_count++; | ||
383 | |||
384 | dev->_file_status = (vfs_read_retval == line_size) ? | ||
385 | IN_PROGRESS : END_OF_FILE; | ||
386 | |||
387 | set_fs(old_fs); | ||
388 | filp_close(myfile, NULL); | ||
389 | } | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static void cx25821_vidups_handler(struct work_struct *work) | ||
395 | { | ||
396 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, | ||
397 | _irq_work_entry); | ||
398 | |||
399 | if (!dev) { | ||
400 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", | ||
401 | __func__); | ||
402 | return; | ||
403 | } | 327 | } |
404 | 328 | ||
405 | cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select]. | 329 | frame_offset = out->cur_frame_index ? frame_size : 0; |
406 | sram_channels); | ||
407 | } | ||
408 | |||
409 | static int cx25821_openfile(struct cx25821_dev *dev, | ||
410 | struct sram_channel *sram_ch) | ||
411 | { | ||
412 | struct file *myfile; | ||
413 | int i = 0, j = 0; | ||
414 | int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? | ||
415 | Y411_LINE_SZ : Y422_LINE_SZ; | ||
416 | ssize_t vfs_read_retval = 0; | ||
417 | char mybuf[line_size]; | ||
418 | loff_t pos; | ||
419 | loff_t offset = (unsigned long)0; | ||
420 | mm_segment_t old_fs; | ||
421 | |||
422 | myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0); | ||
423 | |||
424 | if (IS_ERR(myfile)) { | ||
425 | const int open_errno = -PTR_ERR(myfile); | ||
426 | pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", | ||
427 | __func__, dev->_filename, open_errno); | ||
428 | return PTR_ERR(myfile); | ||
429 | } else { | ||
430 | if (!(myfile->f_op)) { | ||
431 | pr_err("%s(): File has no file operations registered!\n", | ||
432 | __func__); | ||
433 | filp_close(myfile, NULL); | ||
434 | return -EIO; | ||
435 | } | ||
436 | |||
437 | if (!myfile->f_op->read) { | ||
438 | pr_err("%s(): File has no READ operations registered! Returning\n", | ||
439 | __func__); | ||
440 | filp_close(myfile, NULL); | ||
441 | return -EIO; | ||
442 | } | ||
443 | |||
444 | pos = myfile->f_pos; | ||
445 | old_fs = get_fs(); | ||
446 | set_fs(KERNEL_DS); | ||
447 | |||
448 | for (j = 0; j < NUM_FRAMES; j++) { | ||
449 | for (i = 0; i < dev->_lines_count; i++) { | ||
450 | pos = offset; | ||
451 | |||
452 | vfs_read_retval = vfs_read(myfile, mybuf, | ||
453 | line_size, &pos); | ||
454 | |||
455 | if (vfs_read_retval > 0 | ||
456 | && vfs_read_retval == line_size | ||
457 | && dev->_data_buf_virt_addr != NULL) { | ||
458 | memcpy((void *)(dev-> | ||
459 | _data_buf_virt_addr + | ||
460 | offset / 4), mybuf, | ||
461 | vfs_read_retval); | ||
462 | } | ||
463 | |||
464 | offset += vfs_read_retval; | ||
465 | |||
466 | if (vfs_read_retval < line_size) { | ||
467 | pr_info("Done: exit %s() since no more bytes to read from Video file\n", | ||
468 | __func__); | ||
469 | break; | ||
470 | } | ||
471 | } | ||
472 | 330 | ||
473 | if (i > 0) | 331 | if (frame_size - curpos < count) |
474 | dev->_frame_count++; | 332 | count = frame_size - curpos; |
475 | 333 | memcpy((char *)out->_data_buf_virt_addr + frame_offset + curpos, | |
476 | if (vfs_read_retval < line_size) | 334 | data, count); |
477 | break; | 335 | curpos += count; |
478 | } | 336 | if (curpos == frame_size) { |
479 | 337 | out->_frame_count++; | |
480 | dev->_file_status = (vfs_read_retval == line_size) ? | 338 | curpos = 0; |
481 | IN_PROGRESS : END_OF_FILE; | ||
482 | |||
483 | set_fs(old_fs); | ||
484 | myfile->f_pos = 0; | ||
485 | filp_close(myfile, NULL); | ||
486 | } | 339 | } |
340 | out->curpos = curpos; | ||
487 | 341 | ||
488 | return 0; | 342 | return count; |
489 | } | 343 | } |
490 | 344 | ||
491 | static int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | 345 | static int cx25821_upstream_buffer_prepare(struct cx25821_channel *chan, |
492 | struct sram_channel *sram_ch, | 346 | const struct sram_channel *sram_ch, |
493 | int bpl) | 347 | int bpl) |
494 | { | 348 | { |
349 | struct cx25821_video_out_data *out = chan->out; | ||
350 | struct cx25821_dev *dev = chan->dev; | ||
495 | int ret = 0; | 351 | int ret = 0; |
496 | dma_addr_t dma_addr; | 352 | dma_addr_t dma_addr; |
497 | dma_addr_t data_dma_addr; | 353 | dma_addr_t data_dma_addr; |
498 | 354 | ||
499 | if (dev->_dma_virt_addr != NULL) | 355 | if (out->_dma_virt_addr != NULL) |
500 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, | 356 | pci_free_consistent(dev->pci, out->upstream_riscbuf_size, |
501 | dev->_dma_virt_addr, dev->_dma_phys_addr); | 357 | out->_dma_virt_addr, out->_dma_phys_addr); |
502 | 358 | ||
503 | dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, | 359 | out->_dma_virt_addr = pci_alloc_consistent(dev->pci, |
504 | dev->upstream_riscbuf_size, &dma_addr); | 360 | out->upstream_riscbuf_size, &dma_addr); |
505 | dev->_dma_virt_start_addr = dev->_dma_virt_addr; | 361 | out->_dma_virt_start_addr = out->_dma_virt_addr; |
506 | dev->_dma_phys_start_addr = dma_addr; | 362 | out->_dma_phys_start_addr = dma_addr; |
507 | dev->_dma_phys_addr = dma_addr; | 363 | out->_dma_phys_addr = dma_addr; |
508 | dev->_risc_size = dev->upstream_riscbuf_size; | 364 | out->_risc_size = out->upstream_riscbuf_size; |
509 | 365 | ||
510 | if (!dev->_dma_virt_addr) { | 366 | if (!out->_dma_virt_addr) { |
511 | pr_err("FAILED to allocate memory for Risc buffer! Returning\n"); | 367 | pr_err("FAILED to allocate memory for Risc buffer! Returning\n"); |
512 | return -ENOMEM; | 368 | return -ENOMEM; |
513 | } | 369 | } |
514 | 370 | ||
515 | /* Clear memory at address */ | 371 | /* Clear memory at address */ |
516 | memset(dev->_dma_virt_addr, 0, dev->_risc_size); | 372 | memset(out->_dma_virt_addr, 0, out->_risc_size); |
517 | 373 | ||
518 | if (dev->_data_buf_virt_addr != NULL) | 374 | if (out->_data_buf_virt_addr != NULL) |
519 | pci_free_consistent(dev->pci, dev->upstream_databuf_size, | 375 | pci_free_consistent(dev->pci, out->upstream_databuf_size, |
520 | dev->_data_buf_virt_addr, | 376 | out->_data_buf_virt_addr, |
521 | dev->_data_buf_phys_addr); | 377 | out->_data_buf_phys_addr); |
522 | /* For Video Data buffer allocation */ | 378 | /* For Video Data buffer allocation */ |
523 | dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, | 379 | out->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, |
524 | dev->upstream_databuf_size, &data_dma_addr); | 380 | out->upstream_databuf_size, &data_dma_addr); |
525 | dev->_data_buf_phys_addr = data_dma_addr; | 381 | out->_data_buf_phys_addr = data_dma_addr; |
526 | dev->_data_buf_size = dev->upstream_databuf_size; | 382 | out->_data_buf_size = out->upstream_databuf_size; |
527 | 383 | ||
528 | if (!dev->_data_buf_virt_addr) { | 384 | if (!out->_data_buf_virt_addr) { |
529 | pr_err("FAILED to allocate memory for data buffer! Returning\n"); | 385 | pr_err("FAILED to allocate memory for data buffer! Returning\n"); |
530 | return -ENOMEM; | 386 | return -ENOMEM; |
531 | } | 387 | } |
532 | 388 | ||
533 | /* Clear memory at address */ | 389 | /* Clear memory at address */ |
534 | memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size); | 390 | memset(out->_data_buf_virt_addr, 0, out->_data_buf_size); |
535 | |||
536 | ret = cx25821_openfile(dev, sram_ch); | ||
537 | if (ret < 0) | ||
538 | return ret; | ||
539 | 391 | ||
540 | /* Create RISC programs */ | 392 | /* Create RISC programs */ |
541 | ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, | 393 | ret = cx25821_risc_buffer_upstream(chan, dev->pci, 0, bpl, |
542 | dev->_lines_count); | 394 | out->_lines_count); |
543 | if (ret < 0) { | 395 | if (ret < 0) { |
544 | pr_info("Failed creating Video Upstream Risc programs!\n"); | 396 | pr_info("Failed creating Video Upstream Risc programs!\n"); |
545 | goto error; | 397 | goto error; |
@@ -551,11 +403,12 @@ error: | |||
551 | return ret; | 403 | return ret; |
552 | } | 404 | } |
553 | 405 | ||
554 | static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | 406 | static int cx25821_video_upstream_irq(struct cx25821_channel *chan, u32 status) |
555 | u32 status) | ||
556 | { | 407 | { |
408 | struct cx25821_video_out_data *out = chan->out; | ||
409 | struct cx25821_dev *dev = chan->dev; | ||
557 | u32 int_msk_tmp; | 410 | u32 int_msk_tmp; |
558 | struct sram_channel *channel = dev->channels[chan_num].sram_channels; | 411 | const struct sram_channel *channel = chan->sram_channels; |
559 | int singlefield_lines = NTSC_FIELD_HEIGHT; | 412 | int singlefield_lines = NTSC_FIELD_HEIGHT; |
560 | int line_size_in_bytes = Y422_LINE_SZ; | 413 | int line_size_in_bytes = Y422_LINE_SZ; |
561 | int odd_risc_prog_size = 0; | 414 | int odd_risc_prog_size = 0; |
@@ -572,16 +425,16 @@ static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
572 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); | 425 | cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); |
573 | cx_write(channel->int_stat, _intr_msk); | 426 | cx_write(channel->int_stat, _intr_msk); |
574 | 427 | ||
575 | spin_lock(&dev->slock); | 428 | wake_up(&out->waitq); |
576 | 429 | ||
577 | dev->_frame_index = prog_cnt; | 430 | spin_lock(&dev->slock); |
578 | 431 | ||
579 | queue_work(dev->_irq_queues, &dev->_irq_work_entry); | 432 | out->_frame_index = prog_cnt; |
580 | 433 | ||
581 | if (dev->_is_first_frame) { | 434 | if (out->_is_first_frame) { |
582 | dev->_is_first_frame = 0; | 435 | out->_is_first_frame = 0; |
583 | 436 | ||
584 | if (dev->_isNTSC) { | 437 | if (out->is_60hz) { |
585 | singlefield_lines += 1; | 438 | singlefield_lines += 1; |
586 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; | 439 | odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE; |
587 | } else { | 440 | } else { |
@@ -589,17 +442,17 @@ static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
589 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; | 442 | odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE; |
590 | } | 443 | } |
591 | 444 | ||
592 | if (dev->_dma_virt_start_addr != NULL) { | 445 | if (out->_dma_virt_start_addr != NULL) { |
593 | line_size_in_bytes = | 446 | line_size_in_bytes = |
594 | (dev->_pixel_format == | 447 | (out->_pixel_format == |
595 | PIXEL_FRMT_411) ? Y411_LINE_SZ : | 448 | PIXEL_FRMT_411) ? Y411_LINE_SZ : |
596 | Y422_LINE_SZ; | 449 | Y422_LINE_SZ; |
597 | risc_phys_jump_addr = | 450 | risc_phys_jump_addr = |
598 | dev->_dma_phys_start_addr + | 451 | out->_dma_phys_start_addr + |
599 | odd_risc_prog_size; | 452 | odd_risc_prog_size; |
600 | 453 | ||
601 | rp = cx25821_update_riscprogram(dev, | 454 | rp = cx25821_update_riscprogram(chan, |
602 | dev->_dma_virt_start_addr, TOP_OFFSET, | 455 | out->_dma_virt_start_addr, TOP_OFFSET, |
603 | line_size_in_bytes, 0x0, | 456 | line_size_in_bytes, 0x0, |
604 | singlefield_lines, FIFO_DISABLE, | 457 | singlefield_lines, FIFO_DISABLE, |
605 | ODD_FIELD); | 458 | ODD_FIELD); |
@@ -626,8 +479,8 @@ static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
626 | __func__); | 479 | __func__); |
627 | } | 480 | } |
628 | 481 | ||
629 | if (dev->_file_status == END_OF_FILE) { | 482 | if (out->_file_status == END_OF_FILE) { |
630 | pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count); | 483 | pr_err("EOF Channel 1 Framecount = %d\n", out->_frame_count); |
631 | return -1; | 484 | return -1; |
632 | } | 485 | } |
633 | /* ElSE, set the interrupt mask register, re-enable irq. */ | 486 | /* ElSE, set the interrupt mask register, re-enable irq. */ |
@@ -639,47 +492,41 @@ static int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
639 | 492 | ||
640 | static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) | 493 | static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) |
641 | { | 494 | { |
642 | struct cx25821_dev *dev = dev_id; | 495 | struct cx25821_channel *chan = dev_id; |
496 | struct cx25821_dev *dev = chan->dev; | ||
643 | u32 vid_status; | 497 | u32 vid_status; |
644 | int handled = 0; | 498 | int handled = 0; |
645 | int channel_num = 0; | 499 | const struct sram_channel *sram_ch; |
646 | struct sram_channel *sram_ch; | ||
647 | 500 | ||
648 | if (!dev) | 501 | if (!dev) |
649 | return -1; | 502 | return -1; |
650 | 503 | ||
651 | channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; | 504 | sram_ch = chan->sram_channels; |
652 | |||
653 | sram_ch = dev->channels[channel_num].sram_channels; | ||
654 | 505 | ||
655 | vid_status = cx_read(sram_ch->int_stat); | 506 | vid_status = cx_read(sram_ch->int_stat); |
656 | 507 | ||
657 | /* Only deal with our interrupt */ | 508 | /* Only deal with our interrupt */ |
658 | if (vid_status) | 509 | if (vid_status) |
659 | handled = cx25821_video_upstream_irq(dev, channel_num, | 510 | handled = cx25821_video_upstream_irq(chan, vid_status); |
660 | vid_status); | ||
661 | |||
662 | if (handled < 0) | ||
663 | cx25821_stop_upstream_video_ch1(dev); | ||
664 | else | ||
665 | handled += handled; | ||
666 | 511 | ||
667 | return IRQ_RETVAL(handled); | 512 | return IRQ_RETVAL(handled); |
668 | } | 513 | } |
669 | 514 | ||
670 | static void cx25821_set_pixelengine(struct cx25821_dev *dev, | 515 | static void cx25821_set_pixelengine(struct cx25821_channel *chan, |
671 | struct sram_channel *ch, | 516 | const struct sram_channel *ch, |
672 | int pix_format) | 517 | int pix_format) |
673 | { | 518 | { |
519 | struct cx25821_video_out_data *out = chan->out; | ||
520 | struct cx25821_dev *dev = chan->dev; | ||
674 | int width = WIDTH_D1; | 521 | int width = WIDTH_D1; |
675 | int height = dev->_lines_count; | 522 | int height = out->_lines_count; |
676 | int num_lines, odd_num_lines; | 523 | int num_lines, odd_num_lines; |
677 | u32 value; | 524 | u32 value; |
678 | int vip_mode = OUTPUT_FRMT_656; | 525 | int vip_mode = OUTPUT_FRMT_656; |
679 | 526 | ||
680 | value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); | 527 | value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7); |
681 | value &= 0xFFFFFFEF; | 528 | value &= 0xFFFFFFEF; |
682 | value |= dev->_isNTSC ? 0 : 0x10; | 529 | value |= out->is_60hz ? 0 : 0x10; |
683 | cx_write(ch->vid_fmt_ctl, value); | 530 | cx_write(ch->vid_fmt_ctl, value); |
684 | 531 | ||
685 | /* set number of active pixels in each line. | 532 | /* set number of active pixels in each line. |
@@ -689,7 +536,7 @@ static void cx25821_set_pixelengine(struct cx25821_dev *dev, | |||
689 | num_lines = (height / 2) & 0x3FF; | 536 | num_lines = (height / 2) & 0x3FF; |
690 | odd_num_lines = num_lines; | 537 | odd_num_lines = num_lines; |
691 | 538 | ||
692 | if (dev->_isNTSC) | 539 | if (out->is_60hz) |
693 | odd_num_lines += 1; | 540 | odd_num_lines += 1; |
694 | 541 | ||
695 | value = (num_lines << 16) | odd_num_lines; | 542 | value = (num_lines << 16) | odd_num_lines; |
@@ -700,9 +547,11 @@ static void cx25821_set_pixelengine(struct cx25821_dev *dev, | |||
700 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); | 547 | cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); |
701 | } | 548 | } |
702 | 549 | ||
703 | static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | 550 | static int cx25821_start_video_dma_upstream(struct cx25821_channel *chan, |
704 | struct sram_channel *sram_ch) | 551 | const struct sram_channel *sram_ch) |
705 | { | 552 | { |
553 | struct cx25821_video_out_data *out = chan->out; | ||
554 | struct cx25821_dev *dev = chan->dev; | ||
706 | u32 tmp = 0; | 555 | u32 tmp = 0; |
707 | int err = 0; | 556 | int err = 0; |
708 | 557 | ||
@@ -715,7 +564,7 @@ static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
715 | /* Set the physical start address of the RISC program in the initial | 564 | /* Set the physical start address of the RISC program in the initial |
716 | * program counter(IPC) member of the cmds. | 565 | * program counter(IPC) member of the cmds. |
717 | */ | 566 | */ |
718 | cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr); | 567 | cx_write(sram_ch->cmds_start + 0, out->_dma_phys_addr); |
719 | /* Risc IPC High 64 bits 63-32 */ | 568 | /* Risc IPC High 64 bits 63-32 */ |
720 | cx_write(sram_ch->cmds_start + 4, 0); | 569 | cx_write(sram_ch->cmds_start + 4, 0); |
721 | 570 | ||
@@ -731,7 +580,7 @@ static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
731 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | 580 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); |
732 | 581 | ||
733 | err = request_irq(dev->pci->irq, cx25821_upstream_irq, | 582 | err = request_irq(dev->pci->irq, cx25821_upstream_irq, |
734 | IRQF_SHARED, dev->name, dev); | 583 | IRQF_SHARED, dev->name, chan); |
735 | if (err < 0) { | 584 | if (err < 0) { |
736 | pr_err("%s: can't get upstream IRQ %d\n", | 585 | pr_err("%s: can't get upstream IRQ %d\n", |
737 | dev->name, dev->pci->irq); | 586 | dev->name, dev->pci->irq); |
@@ -742,8 +591,8 @@ static int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
742 | tmp = cx_read(sram_ch->dma_ctl); | 591 | tmp = cx_read(sram_ch->dma_ctl); |
743 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); | 592 | cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); |
744 | 593 | ||
745 | dev->_is_running = 1; | 594 | out->_is_running = 1; |
746 | dev->_is_first_frame = 1; | 595 | out->_is_first_frame = 1; |
747 | 596 | ||
748 | return 0; | 597 | return 0; |
749 | 598 | ||
@@ -752,107 +601,71 @@ fail_irq: | |||
752 | return err; | 601 | return err; |
753 | } | 602 | } |
754 | 603 | ||
755 | int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | 604 | int cx25821_vidupstream_init(struct cx25821_channel *chan, |
756 | int pixel_format) | 605 | int pixel_format) |
757 | { | 606 | { |
758 | struct sram_channel *sram_ch; | 607 | struct cx25821_video_out_data *out = chan->out; |
608 | struct cx25821_dev *dev = chan->dev; | ||
609 | const struct sram_channel *sram_ch; | ||
759 | u32 tmp; | 610 | u32 tmp; |
760 | int err = 0; | 611 | int err = 0; |
761 | int data_frame_size = 0; | 612 | int data_frame_size = 0; |
762 | int risc_buffer_size = 0; | 613 | int risc_buffer_size = 0; |
763 | int str_length = 0; | ||
764 | 614 | ||
765 | if (dev->_is_running) { | 615 | if (out->_is_running) { |
766 | pr_info("Video Channel is still running so return!\n"); | 616 | pr_info("Video Channel is still running so return!\n"); |
767 | return 0; | 617 | return 0; |
768 | } | 618 | } |
769 | 619 | ||
770 | dev->_channel_upstream_select = channel_select; | 620 | sram_ch = chan->sram_channels; |
771 | sram_ch = dev->channels[channel_select].sram_channels; | ||
772 | 621 | ||
773 | INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); | 622 | out->is_60hz = dev->tvnorm & V4L2_STD_525_60; |
774 | dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); | ||
775 | 623 | ||
776 | if (!dev->_irq_queues) { | ||
777 | pr_err("create_singlethread_workqueue() for Video FAILED!\n"); | ||
778 | return -ENOMEM; | ||
779 | } | ||
780 | /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for | 624 | /* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for |
781 | * channel A-C | 625 | * channel A-C |
782 | */ | 626 | */ |
783 | tmp = cx_read(VID_CH_MODE_SEL); | 627 | tmp = cx_read(VID_CH_MODE_SEL); |
784 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); | 628 | cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); |
785 | 629 | ||
786 | dev->_is_running = 0; | 630 | out->_is_running = 0; |
787 | dev->_frame_count = 0; | 631 | out->_frame_count = 0; |
788 | dev->_file_status = RESET_STATUS; | 632 | out->_file_status = RESET_STATUS; |
789 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | 633 | out->_lines_count = out->is_60hz ? 480 : 576; |
790 | dev->_pixel_format = pixel_format; | 634 | out->_pixel_format = pixel_format; |
791 | dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? | 635 | out->_line_size = (out->_pixel_format == PIXEL_FRMT_422) ? |
792 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | 636 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; |
793 | data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | 637 | data_frame_size = out->is_60hz ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; |
794 | risc_buffer_size = dev->_isNTSC ? | 638 | risc_buffer_size = out->is_60hz ? |
795 | NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | 639 | NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; |
796 | 640 | ||
797 | if (dev->input_filename) { | 641 | out->_is_running = 0; |
798 | str_length = strlen(dev->input_filename); | 642 | out->_frame_count = 0; |
799 | dev->_filename = kmemdup(dev->input_filename, str_length + 1, | 643 | out->_file_status = RESET_STATUS; |
800 | GFP_KERNEL); | 644 | out->_lines_count = out->is_60hz ? 480 : 576; |
801 | 645 | out->_pixel_format = pixel_format; | |
802 | if (!dev->_filename) { | 646 | out->_line_size = (out->_pixel_format == PIXEL_FRMT_422) ? |
803 | err = -ENOENT; | ||
804 | goto error; | ||
805 | } | ||
806 | } else { | ||
807 | str_length = strlen(dev->_defaultname); | ||
808 | dev->_filename = kmemdup(dev->_defaultname, str_length + 1, | ||
809 | GFP_KERNEL); | ||
810 | |||
811 | if (!dev->_filename) { | ||
812 | err = -ENOENT; | ||
813 | goto error; | ||
814 | } | ||
815 | } | ||
816 | |||
817 | /* Default if filename is empty string */ | ||
818 | if (strcmp(dev->_filename, "") == 0) { | ||
819 | if (dev->_isNTSC) { | ||
820 | dev->_filename = | ||
821 | (dev->_pixel_format == PIXEL_FRMT_411) ? | ||
822 | "/root/vid411.yuv" : "/root/vidtest.yuv"; | ||
823 | } else { | ||
824 | dev->_filename = | ||
825 | (dev->_pixel_format == PIXEL_FRMT_411) ? | ||
826 | "/root/pal411.yuv" : "/root/pal422.yuv"; | ||
827 | } | ||
828 | } | ||
829 | |||
830 | dev->_is_running = 0; | ||
831 | dev->_frame_count = 0; | ||
832 | dev->_file_status = RESET_STATUS; | ||
833 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | ||
834 | dev->_pixel_format = pixel_format; | ||
835 | dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? | ||
836 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | 647 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; |
648 | out->curpos = 0; | ||
649 | init_waitqueue_head(&out->waitq); | ||
837 | 650 | ||
838 | err = cx25821_sram_channel_setup_upstream(dev, sram_ch, | 651 | err = cx25821_sram_channel_setup_upstream(dev, sram_ch, |
839 | dev->_line_size, 0); | 652 | out->_line_size, 0); |
840 | 653 | ||
841 | /* setup fifo + format */ | 654 | /* setup fifo + format */ |
842 | cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); | 655 | cx25821_set_pixelengine(chan, sram_ch, out->_pixel_format); |
843 | 656 | ||
844 | dev->upstream_riscbuf_size = risc_buffer_size * 2; | 657 | out->upstream_riscbuf_size = risc_buffer_size * 2; |
845 | dev->upstream_databuf_size = data_frame_size * 2; | 658 | out->upstream_databuf_size = data_frame_size * 2; |
846 | 659 | ||
847 | /* Allocating buffers and prepare RISC program */ | 660 | /* Allocating buffers and prepare RISC program */ |
848 | err = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size); | 661 | err = cx25821_upstream_buffer_prepare(chan, sram_ch, out->_line_size); |
849 | if (err < 0) { | 662 | if (err < 0) { |
850 | pr_err("%s: Failed to set up Video upstream buffers!\n", | 663 | pr_err("%s: Failed to set up Video upstream buffers!\n", |
851 | dev->name); | 664 | dev->name); |
852 | goto error; | 665 | goto error; |
853 | } | 666 | } |
854 | 667 | ||
855 | cx25821_start_video_dma_upstream(dev, sram_ch); | 668 | cx25821_start_video_dma_upstream(chan, sram_ch); |
856 | 669 | ||
857 | return 0; | 670 | return 0; |
858 | 671 | ||
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c index 1465591d000c..b194138961df 100644 --- a/drivers/media/pci/cx25821/cx25821-video.c +++ b/drivers/media/pci/cx25821/cx25821-video.c | |||
@@ -33,13 +33,10 @@ MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | |||
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
35 | static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | 35 | static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; |
36 | static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | ||
37 | 36 | ||
38 | module_param_array(video_nr, int, NULL, 0444); | 37 | module_param_array(video_nr, int, NULL, 0444); |
39 | module_param_array(radio_nr, int, NULL, 0444); | ||
40 | 38 | ||
41 | MODULE_PARM_DESC(video_nr, "video device numbers"); | 39 | MODULE_PARM_DESC(video_nr, "video device numbers"); |
42 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | ||
43 | 40 | ||
44 | static unsigned int video_debug = VIDEO_DEBUG; | 41 | static unsigned int video_debug = VIDEO_DEBUG; |
45 | module_param(video_debug, int, 0644); | 42 | module_param(video_debug, int, 0644); |
@@ -49,24 +46,14 @@ static unsigned int irq_debug; | |||
49 | module_param(irq_debug, int, 0644); | 46 | module_param(irq_debug, int, 0644); |
50 | MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); | 47 | MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); |
51 | 48 | ||
52 | unsigned int vid_limit = 16; | 49 | static unsigned int vid_limit = 16; |
53 | module_param(vid_limit, int, 0644); | 50 | module_param(vid_limit, int, 0644); |
54 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | 51 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); |
55 | 52 | ||
56 | static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num); | ||
57 | |||
58 | static const struct v4l2_file_operations video_fops; | ||
59 | static const struct v4l2_ioctl_ops video_ioctl_ops; | ||
60 | |||
61 | #define FORMAT_FLAGS_PACKED 0x01 | 53 | #define FORMAT_FLAGS_PACKED 0x01 |
62 | 54 | ||
63 | struct cx25821_fmt formats[] = { | 55 | static const struct cx25821_fmt formats[] = { |
64 | { | 56 | { |
65 | .name = "8 bpp, gray", | ||
66 | .fourcc = V4L2_PIX_FMT_GREY, | ||
67 | .depth = 8, | ||
68 | .flags = FORMAT_FLAGS_PACKED, | ||
69 | }, { | ||
70 | .name = "4:1:1, packed, Y41P", | 57 | .name = "4:1:1, packed, Y41P", |
71 | .fourcc = V4L2_PIX_FMT_Y41P, | 58 | .fourcc = V4L2_PIX_FMT_Y41P, |
72 | .depth = 12, | 59 | .depth = 12, |
@@ -76,36 +63,16 @@ struct cx25821_fmt formats[] = { | |||
76 | .fourcc = V4L2_PIX_FMT_YUYV, | 63 | .fourcc = V4L2_PIX_FMT_YUYV, |
77 | .depth = 16, | 64 | .depth = 16, |
78 | .flags = FORMAT_FLAGS_PACKED, | 65 | .flags = FORMAT_FLAGS_PACKED, |
79 | }, { | ||
80 | .name = "4:2:2, packed, UYVY", | ||
81 | .fourcc = V4L2_PIX_FMT_UYVY, | ||
82 | .depth = 16, | ||
83 | .flags = FORMAT_FLAGS_PACKED, | ||
84 | }, { | ||
85 | .name = "4:2:0, YUV", | ||
86 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
87 | .depth = 12, | ||
88 | .flags = FORMAT_FLAGS_PACKED, | ||
89 | }, | 66 | }, |
90 | }; | 67 | }; |
91 | 68 | ||
92 | int cx25821_get_format_size(void) | 69 | static const struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) |
93 | { | ||
94 | return ARRAY_SIZE(formats); | ||
95 | } | ||
96 | |||
97 | struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) | ||
98 | { | 70 | { |
99 | unsigned int i; | 71 | unsigned int i; |
100 | 72 | ||
101 | if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P) | ||
102 | return formats + 1; | ||
103 | |||
104 | for (i = 0; i < ARRAY_SIZE(formats); i++) | 73 | for (i = 0; i < ARRAY_SIZE(formats); i++) |
105 | if (formats[i].fourcc == fourcc) | 74 | if (formats[i].fourcc == fourcc) |
106 | return formats + i; | 75 | return formats + i; |
107 | |||
108 | pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc); | ||
109 | return NULL; | 76 | return NULL; |
110 | } | 77 | } |
111 | 78 | ||
@@ -144,129 +111,10 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, | |||
144 | pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc); | 111 | pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc); |
145 | } | 112 | } |
146 | 113 | ||
147 | #ifdef TUNER_FLAG | ||
148 | int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) | ||
149 | { | ||
150 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", | ||
151 | __func__, (unsigned int)norm, v4l2_norm_to_name(norm)); | ||
152 | |||
153 | dev->tvnorm = norm; | ||
154 | |||
155 | /* Tell the internal A/V decoder */ | ||
156 | cx25821_call_all(dev, core, s_std, norm); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | #endif | ||
161 | |||
162 | struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | ||
163 | struct pci_dev *pci, | ||
164 | struct video_device *template, | ||
165 | char *type) | ||
166 | { | ||
167 | struct video_device *vfd; | ||
168 | dprintk(1, "%s()\n", __func__); | ||
169 | |||
170 | vfd = video_device_alloc(); | ||
171 | if (NULL == vfd) | ||
172 | return NULL; | ||
173 | *vfd = *template; | ||
174 | vfd->v4l2_dev = &dev->v4l2_dev; | ||
175 | vfd->release = video_device_release; | ||
176 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, | ||
177 | cx25821_boards[dev->board].name); | ||
178 | video_set_drvdata(vfd, dev); | ||
179 | return vfd; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | ||
184 | { | ||
185 | int i; | ||
186 | |||
187 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | ||
188 | return -EINVAL; | ||
189 | for (i = 0; i < CX25821_CTLS; i++) | ||
190 | if (cx25821_ctls[i].v.id == qctrl->id) | ||
191 | break; | ||
192 | if (i == CX25821_CTLS) { | ||
193 | *qctrl = no_ctl; | ||
194 | return 0; | ||
195 | } | ||
196 | *qctrl = cx25821_ctls[i].v; | ||
197 | return 0; | ||
198 | } | ||
199 | */ | ||
200 | |||
201 | /* resource management */ | ||
202 | int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, | ||
203 | unsigned int bit) | ||
204 | { | ||
205 | dprintk(1, "%s()\n", __func__); | ||
206 | if (fh->resources & bit) | ||
207 | /* have it already allocated */ | ||
208 | return 1; | ||
209 | |||
210 | /* is it free? */ | ||
211 | mutex_lock(&dev->lock); | ||
212 | if (dev->channels[fh->channel_id].resources & bit) { | ||
213 | /* no, someone else uses it */ | ||
214 | mutex_unlock(&dev->lock); | ||
215 | return 0; | ||
216 | } | ||
217 | /* it's free, grab it */ | ||
218 | fh->resources |= bit; | ||
219 | dev->channels[fh->channel_id].resources |= bit; | ||
220 | dprintk(1, "res: get %d\n", bit); | ||
221 | mutex_unlock(&dev->lock); | ||
222 | return 1; | ||
223 | } | ||
224 | |||
225 | int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit) | ||
226 | { | ||
227 | return fh->resources & bit; | ||
228 | } | ||
229 | |||
230 | int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit) | ||
231 | { | ||
232 | return fh->dev->channels[fh->channel_id].resources & bit; | ||
233 | } | ||
234 | |||
235 | void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, | ||
236 | unsigned int bits) | ||
237 | { | ||
238 | BUG_ON((fh->resources & bits) != bits); | ||
239 | dprintk(1, "%s()\n", __func__); | ||
240 | |||
241 | mutex_lock(&dev->lock); | ||
242 | fh->resources &= ~bits; | ||
243 | dev->channels[fh->channel_id].resources &= ~bits; | ||
244 | dprintk(1, "res: put %d\n", bits); | ||
245 | mutex_unlock(&dev->lock); | ||
246 | } | ||
247 | |||
248 | int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) | ||
249 | { | ||
250 | struct v4l2_routing route; | ||
251 | memset(&route, 0, sizeof(route)); | ||
252 | |||
253 | dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", | ||
254 | __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, | ||
255 | INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); | ||
256 | dev->input = input; | ||
257 | |||
258 | route.input = INPUT(input)->vmux; | ||
259 | |||
260 | /* Tell the internal A/V decoder */ | ||
261 | cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | int cx25821_start_video_dma(struct cx25821_dev *dev, | 114 | int cx25821_start_video_dma(struct cx25821_dev *dev, |
267 | struct cx25821_dmaqueue *q, | 115 | struct cx25821_dmaqueue *q, |
268 | struct cx25821_buffer *buf, | 116 | struct cx25821_buffer *buf, |
269 | struct sram_channel *channel) | 117 | const struct sram_channel *channel) |
270 | { | 118 | { |
271 | int tmp = 0; | 119 | int tmp = 0; |
272 | 120 | ||
@@ -293,7 +141,7 @@ int cx25821_start_video_dma(struct cx25821_dev *dev, | |||
293 | 141 | ||
294 | static int cx25821_restart_video_queue(struct cx25821_dev *dev, | 142 | static int cx25821_restart_video_queue(struct cx25821_dev *dev, |
295 | struct cx25821_dmaqueue *q, | 143 | struct cx25821_dmaqueue *q, |
296 | struct sram_channel *channel) | 144 | const struct sram_channel *channel) |
297 | { | 145 | { |
298 | struct cx25821_buffer *buf, *prev; | 146 | struct cx25821_buffer *buf, *prev; |
299 | struct list_head *item; | 147 | struct list_head *item; |
@@ -346,8 +194,8 @@ static void cx25821_vid_timeout(unsigned long data) | |||
346 | { | 194 | { |
347 | struct cx25821_data *timeout_data = (struct cx25821_data *)data; | 195 | struct cx25821_data *timeout_data = (struct cx25821_data *)data; |
348 | struct cx25821_dev *dev = timeout_data->dev; | 196 | struct cx25821_dev *dev = timeout_data->dev; |
349 | struct sram_channel *channel = timeout_data->channel; | 197 | const struct sram_channel *channel = timeout_data->channel; |
350 | struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq; | 198 | struct cx25821_dmaqueue *q = &dev->channels[channel->i].dma_vidq; |
351 | struct cx25821_buffer *buf; | 199 | struct cx25821_buffer *buf; |
352 | unsigned long flags; | 200 | unsigned long flags; |
353 | 201 | ||
@@ -373,7 +221,7 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) | |||
373 | u32 count = 0; | 221 | u32 count = 0; |
374 | int handled = 0; | 222 | int handled = 0; |
375 | u32 mask; | 223 | u32 mask; |
376 | struct sram_channel *channel = dev->channels[chan_num].sram_channels; | 224 | const struct sram_channel *channel = dev->channels[chan_num].sram_channels; |
377 | 225 | ||
378 | mask = cx_read(channel->int_msk); | 226 | mask = cx_read(channel->int_msk); |
379 | if (0 == (status & mask)) | 227 | if (0 == (status & mask)) |
@@ -393,7 +241,7 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) | |||
393 | if (status & FLD_VID_DST_RISC1) { | 241 | if (status & FLD_VID_DST_RISC1) { |
394 | spin_lock(&dev->slock); | 242 | spin_lock(&dev->slock); |
395 | count = cx_read(channel->gpcnt); | 243 | count = cx_read(channel->gpcnt); |
396 | cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq, | 244 | cx25821_video_wakeup(dev, &dev->channels[channel->i].dma_vidq, |
397 | count); | 245 | count); |
398 | spin_unlock(&dev->slock); | 246 | spin_unlock(&dev->slock); |
399 | handled++; | 247 | handled++; |
@@ -404,122 +252,19 @@ int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) | |||
404 | dprintk(2, "stopper video\n"); | 252 | dprintk(2, "stopper video\n"); |
405 | spin_lock(&dev->slock); | 253 | spin_lock(&dev->slock); |
406 | cx25821_restart_video_queue(dev, | 254 | cx25821_restart_video_queue(dev, |
407 | &dev->channels[channel->i].vidq, channel); | 255 | &dev->channels[channel->i].dma_vidq, channel); |
408 | spin_unlock(&dev->slock); | 256 | spin_unlock(&dev->slock); |
409 | handled++; | 257 | handled++; |
410 | } | 258 | } |
411 | return handled; | 259 | return handled; |
412 | } | 260 | } |
413 | 261 | ||
414 | void cx25821_videoioctl_unregister(struct cx25821_dev *dev) | 262 | static int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, |
415 | { | ||
416 | if (dev->ioctl_dev) { | ||
417 | if (video_is_registered(dev->ioctl_dev)) | ||
418 | video_unregister_device(dev->ioctl_dev); | ||
419 | else | ||
420 | video_device_release(dev->ioctl_dev); | ||
421 | |||
422 | dev->ioctl_dev = NULL; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) | ||
427 | { | ||
428 | cx_clear(PCI_INT_MSK, 1); | ||
429 | |||
430 | if (dev->channels[chan_num].video_dev) { | ||
431 | if (video_is_registered(dev->channels[chan_num].video_dev)) | ||
432 | video_unregister_device( | ||
433 | dev->channels[chan_num].video_dev); | ||
434 | else | ||
435 | video_device_release( | ||
436 | dev->channels[chan_num].video_dev); | ||
437 | |||
438 | dev->channels[chan_num].video_dev = NULL; | ||
439 | |||
440 | btcx_riscmem_free(dev->pci, | ||
441 | &dev->channels[chan_num].vidq.stopper); | ||
442 | |||
443 | pr_warn("device %d released!\n", chan_num); | ||
444 | } | ||
445 | |||
446 | } | ||
447 | |||
448 | int cx25821_video_register(struct cx25821_dev *dev) | ||
449 | { | ||
450 | int err; | ||
451 | int i; | ||
452 | |||
453 | struct video_device cx25821_video_device = { | ||
454 | .name = "cx25821-video", | ||
455 | .fops = &video_fops, | ||
456 | .minor = -1, | ||
457 | .ioctl_ops = &video_ioctl_ops, | ||
458 | .tvnorms = CX25821_NORMS, | ||
459 | .current_norm = V4L2_STD_NTSC_M, | ||
460 | }; | ||
461 | |||
462 | spin_lock_init(&dev->slock); | ||
463 | |||
464 | for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) { | ||
465 | cx25821_init_controls(dev, i); | ||
466 | |||
467 | cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper, | ||
468 | dev->channels[i].sram_channels->dma_ctl, 0x11, 0); | ||
469 | |||
470 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; | ||
471 | dev->channels[i].video_dev = NULL; | ||
472 | dev->channels[i].resources = 0; | ||
473 | |||
474 | cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff); | ||
475 | |||
476 | INIT_LIST_HEAD(&dev->channels[i].vidq.active); | ||
477 | INIT_LIST_HEAD(&dev->channels[i].vidq.queued); | ||
478 | |||
479 | dev->channels[i].timeout_data.dev = dev; | ||
480 | dev->channels[i].timeout_data.channel = | ||
481 | &cx25821_sram_channels[i]; | ||
482 | dev->channels[i].vidq.timeout.function = cx25821_vid_timeout; | ||
483 | dev->channels[i].vidq.timeout.data = | ||
484 | (unsigned long)&dev->channels[i].timeout_data; | ||
485 | init_timer(&dev->channels[i].vidq.timeout); | ||
486 | |||
487 | /* register v4l devices */ | ||
488 | dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci, | ||
489 | &cx25821_video_device, "video"); | ||
490 | |||
491 | err = video_register_device(dev->channels[i].video_dev, | ||
492 | VFL_TYPE_GRABBER, video_nr[dev->nr]); | ||
493 | |||
494 | if (err < 0) | ||
495 | goto fail_unreg; | ||
496 | |||
497 | } | ||
498 | |||
499 | /* set PCI interrupt */ | ||
500 | cx_set(PCI_INT_MSK, 0xff); | ||
501 | |||
502 | /* initial device configuration */ | ||
503 | mutex_lock(&dev->lock); | ||
504 | #ifdef TUNER_FLAG | ||
505 | dev->tvnorm = cx25821_video_device.current_norm; | ||
506 | cx25821_set_tvnorm(dev, dev->tvnorm); | ||
507 | #endif | ||
508 | mutex_unlock(&dev->lock); | ||
509 | |||
510 | return 0; | ||
511 | |||
512 | fail_unreg: | ||
513 | cx25821_video_unregister(dev, i); | ||
514 | return err; | ||
515 | } | ||
516 | |||
517 | int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, | ||
518 | unsigned int *size) | 263 | unsigned int *size) |
519 | { | 264 | { |
520 | struct cx25821_fh *fh = q->priv_data; | 265 | struct cx25821_channel *chan = q->priv_data; |
521 | 266 | ||
522 | *size = fh->fmt->depth * fh->width * fh->height >> 3; | 267 | *size = chan->fmt->depth * chan->width * chan->height >> 3; |
523 | 268 | ||
524 | if (0 == *count) | 269 | if (0 == *count) |
525 | *count = 32; | 270 | *count = 32; |
@@ -530,35 +275,34 @@ int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
530 | return 0; | 275 | return 0; |
531 | } | 276 | } |
532 | 277 | ||
533 | int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 278 | static int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
534 | enum v4l2_field field) | 279 | enum v4l2_field field) |
535 | { | 280 | { |
536 | struct cx25821_fh *fh = q->priv_data; | 281 | struct cx25821_channel *chan = q->priv_data; |
537 | struct cx25821_dev *dev = fh->dev; | 282 | struct cx25821_dev *dev = chan->dev; |
538 | struct cx25821_buffer *buf = | 283 | struct cx25821_buffer *buf = |
539 | container_of(vb, struct cx25821_buffer, vb); | 284 | container_of(vb, struct cx25821_buffer, vb); |
540 | int rc, init_buffer = 0; | 285 | int rc, init_buffer = 0; |
541 | u32 line0_offset; | 286 | u32 line0_offset; |
542 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | 287 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); |
543 | int bpl_local = LINE_SIZE_D1; | 288 | int bpl_local = LINE_SIZE_D1; |
544 | int channel_opened = fh->channel_id; | ||
545 | 289 | ||
546 | BUG_ON(NULL == fh->fmt); | 290 | BUG_ON(NULL == chan->fmt); |
547 | if (fh->width < 48 || fh->width > 720 || | 291 | if (chan->width < 48 || chan->width > 720 || |
548 | fh->height < 32 || fh->height > 576) | 292 | chan->height < 32 || chan->height > 576) |
549 | return -EINVAL; | 293 | return -EINVAL; |
550 | 294 | ||
551 | buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; | 295 | buf->vb.size = (chan->width * chan->height * chan->fmt->depth) >> 3; |
552 | 296 | ||
553 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 297 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
554 | return -EINVAL; | 298 | return -EINVAL; |
555 | 299 | ||
556 | if (buf->fmt != fh->fmt || | 300 | if (buf->fmt != chan->fmt || |
557 | buf->vb.width != fh->width || | 301 | buf->vb.width != chan->width || |
558 | buf->vb.height != fh->height || buf->vb.field != field) { | 302 | buf->vb.height != chan->height || buf->vb.field != field) { |
559 | buf->fmt = fh->fmt; | 303 | buf->fmt = chan->fmt; |
560 | buf->vb.width = fh->width; | 304 | buf->vb.width = chan->width; |
561 | buf->vb.height = fh->height; | 305 | buf->vb.height = chan->height; |
562 | buf->vb.field = field; | 306 | buf->vb.field = field; |
563 | init_buffer = 1; | 307 | init_buffer = 1; |
564 | } | 308 | } |
@@ -575,34 +319,21 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
575 | dprintk(1, "init_buffer=%d\n", init_buffer); | 319 | dprintk(1, "init_buffer=%d\n", init_buffer); |
576 | 320 | ||
577 | if (init_buffer) { | 321 | if (init_buffer) { |
578 | 322 | if (chan->pixel_formats == PIXEL_FRMT_411) | |
579 | channel_opened = dev->channel_opened; | ||
580 | if (channel_opened < 0 || channel_opened > 7) | ||
581 | channel_opened = 7; | ||
582 | |||
583 | if (dev->channels[channel_opened].pixel_formats == | ||
584 | PIXEL_FRMT_411) | ||
585 | buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; | 323 | buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; |
586 | else | 324 | else |
587 | buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); | 325 | buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); |
588 | 326 | ||
589 | if (dev->channels[channel_opened].pixel_formats == | 327 | if (chan->pixel_formats == PIXEL_FRMT_411) { |
590 | PIXEL_FRMT_411) { | ||
591 | bpl_local = buf->bpl; | 328 | bpl_local = buf->bpl; |
592 | } else { | 329 | } else { |
593 | bpl_local = buf->bpl; /* Default */ | 330 | bpl_local = buf->bpl; /* Default */ |
594 | 331 | ||
595 | if (channel_opened >= 0 && channel_opened <= 7) { | 332 | if (chan->use_cif_resolution) { |
596 | if (dev->channels[channel_opened] | 333 | if (dev->tvnorm & V4L2_STD_625_50) |
597 | .use_cif_resolution) { | 334 | bpl_local = 352 << 1; |
598 | if (dev->tvnorm & V4L2_STD_PAL_BG || | 335 | else |
599 | dev->tvnorm & V4L2_STD_PAL_DK) | 336 | bpl_local = chan->cif_width << 1; |
600 | bpl_local = 352 << 1; | ||
601 | else | ||
602 | bpl_local = dev->channels[ | ||
603 | channel_opened]. | ||
604 | cif_width << 1; | ||
605 | } | ||
606 | } | 337 | } |
607 | } | 338 | } |
608 | 339 | ||
@@ -645,8 +376,8 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
645 | } | 376 | } |
646 | 377 | ||
647 | dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", | 378 | dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", |
648 | buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, | 379 | buf, buf->vb.i, chan->width, chan->height, chan->fmt->depth, |
649 | fh->fmt->name, (unsigned long)buf->risc.dma); | 380 | chan->fmt->name, (unsigned long)buf->risc.dma); |
650 | 381 | ||
651 | buf->vb.state = VIDEOBUF_PREPARED; | 382 | buf->vb.state = VIDEOBUF_PREPARED; |
652 | 383 | ||
@@ -657,7 +388,7 @@ fail: | |||
657 | return rc; | 388 | return rc; |
658 | } | 389 | } |
659 | 390 | ||
660 | void cx25821_buffer_release(struct videobuf_queue *q, | 391 | static void cx25821_buffer_release(struct videobuf_queue *q, |
661 | struct videobuf_buffer *vb) | 392 | struct videobuf_buffer *vb) |
662 | { | 393 | { |
663 | struct cx25821_buffer *buf = | 394 | struct cx25821_buffer *buf = |
@@ -666,33 +397,11 @@ void cx25821_buffer_release(struct videobuf_queue *q, | |||
666 | cx25821_free_buffer(q, buf); | 397 | cx25821_free_buffer(q, buf); |
667 | } | 398 | } |
668 | 399 | ||
669 | struct videobuf_queue *get_queue(struct cx25821_fh *fh) | 400 | static int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) |
670 | { | ||
671 | switch (fh->type) { | ||
672 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
673 | return &fh->vidq; | ||
674 | default: | ||
675 | BUG(); | ||
676 | return NULL; | ||
677 | } | ||
678 | } | ||
679 | |||
680 | int cx25821_get_resource(struct cx25821_fh *fh, int resource) | ||
681 | { | ||
682 | switch (fh->type) { | ||
683 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
684 | return resource; | ||
685 | default: | ||
686 | BUG(); | ||
687 | return 0; | ||
688 | } | ||
689 | } | ||
690 | |||
691 | int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) | ||
692 | { | 401 | { |
693 | struct cx25821_fh *fh = file->private_data; | 402 | struct cx25821_channel *chan = video_drvdata(file); |
694 | 403 | ||
695 | return videobuf_mmap_mapper(get_queue(fh), vma); | 404 | return videobuf_mmap_mapper(&chan->vidq, vma); |
696 | } | 405 | } |
697 | 406 | ||
698 | 407 | ||
@@ -701,9 +410,9 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
701 | struct cx25821_buffer *buf = | 410 | struct cx25821_buffer *buf = |
702 | container_of(vb, struct cx25821_buffer, vb); | 411 | container_of(vb, struct cx25821_buffer, vb); |
703 | struct cx25821_buffer *prev; | 412 | struct cx25821_buffer *prev; |
704 | struct cx25821_fh *fh = vq->priv_data; | 413 | struct cx25821_channel *chan = vq->priv_data; |
705 | struct cx25821_dev *dev = fh->dev; | 414 | struct cx25821_dev *dev = chan->dev; |
706 | struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq; | 415 | struct cx25821_dmaqueue *q = &dev->channels[chan->id].dma_vidq; |
707 | 416 | ||
708 | /* add jump to stopper */ | 417 | /* add jump to stopper */ |
709 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 418 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); |
@@ -720,8 +429,7 @@ static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | |||
720 | 429 | ||
721 | } else if (list_empty(&q->active)) { | 430 | } else if (list_empty(&q->active)) { |
722 | list_add_tail(&buf->vb.queue, &q->active); | 431 | list_add_tail(&buf->vb.queue, &q->active); |
723 | cx25821_start_video_dma(dev, q, buf, | 432 | cx25821_start_video_dma(dev, q, buf, chan->sram_channels); |
724 | dev->channels[fh->channel_id].sram_channels); | ||
725 | buf->vb.state = VIDEOBUF_ACTIVE; | 433 | buf->vb.state = VIDEOBUF_ACTIVE; |
726 | buf->count = q->count++; | 434 | buf->count = q->count++; |
727 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | 435 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); |
@@ -762,1183 +470,487 @@ static struct videobuf_queue_ops cx25821_video_qops = { | |||
762 | .buf_release = cx25821_buffer_release, | 470 | .buf_release = cx25821_buffer_release, |
763 | }; | 471 | }; |
764 | 472 | ||
765 | static int video_open(struct file *file) | ||
766 | { | ||
767 | struct video_device *vdev = video_devdata(file); | ||
768 | struct cx25821_dev *h, *dev = video_drvdata(file); | ||
769 | struct cx25821_fh *fh; | ||
770 | struct list_head *list; | ||
771 | int minor = video_devdata(file)->minor; | ||
772 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
773 | u32 pix_format; | ||
774 | int ch_id = 0; | ||
775 | int i; | ||
776 | |||
777 | dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev), | ||
778 | v4l2_type_names[type]); | ||
779 | |||
780 | /* allocate + initialize per filehandle data */ | ||
781 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | ||
782 | if (NULL == fh) | ||
783 | return -ENOMEM; | ||
784 | |||
785 | mutex_lock(&cx25821_devlist_mutex); | ||
786 | |||
787 | list_for_each(list, &cx25821_devlist) | ||
788 | { | ||
789 | h = list_entry(list, struct cx25821_dev, devlist); | ||
790 | |||
791 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { | ||
792 | if (h->channels[i].video_dev && | ||
793 | h->channels[i].video_dev->minor == minor) { | ||
794 | dev = h; | ||
795 | ch_id = i; | ||
796 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
797 | } | ||
798 | } | ||
799 | } | ||
800 | |||
801 | if (NULL == dev) { | ||
802 | mutex_unlock(&cx25821_devlist_mutex); | ||
803 | kfree(fh); | ||
804 | return -ENODEV; | ||
805 | } | ||
806 | |||
807 | file->private_data = fh; | ||
808 | fh->dev = dev; | ||
809 | fh->type = type; | ||
810 | fh->width = 720; | ||
811 | fh->channel_id = ch_id; | ||
812 | |||
813 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | ||
814 | fh->height = 576; | ||
815 | else | ||
816 | fh->height = 480; | ||
817 | |||
818 | dev->channel_opened = fh->channel_id; | ||
819 | if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411) | ||
820 | pix_format = V4L2_PIX_FMT_Y41P; | ||
821 | else | ||
822 | pix_format = V4L2_PIX_FMT_YUYV; | ||
823 | fh->fmt = cx25821_format_by_fourcc(pix_format); | ||
824 | |||
825 | v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); | ||
826 | |||
827 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev, | ||
828 | &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
829 | V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), | ||
830 | fh, NULL); | ||
831 | |||
832 | dprintk(1, "post videobuf_queue_init()\n"); | ||
833 | mutex_unlock(&cx25821_devlist_mutex); | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | 473 | static ssize_t video_read(struct file *file, char __user * data, size_t count, |
839 | loff_t *ppos) | 474 | loff_t *ppos) |
840 | { | 475 | { |
841 | struct cx25821_fh *fh = file->private_data; | 476 | struct v4l2_fh *fh = file->private_data; |
842 | 477 | struct cx25821_channel *chan = video_drvdata(file); | |
843 | switch (fh->type) { | 478 | struct cx25821_dev *dev = chan->dev; |
844 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 479 | int err = 0; |
845 | if (cx25821_res_locked(fh, RESOURCE_VIDEO0)) | ||
846 | return -EBUSY; | ||
847 | 480 | ||
848 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 481 | if (mutex_lock_interruptible(&dev->lock)) |
849 | file->f_flags & O_NONBLOCK); | 482 | return -ERESTARTSYS; |
850 | 483 | if (chan->streaming_fh && chan->streaming_fh != fh) { | |
851 | default: | 484 | err = -EBUSY; |
852 | BUG(); | 485 | goto unlock; |
853 | return 0; | ||
854 | } | 486 | } |
487 | chan->streaming_fh = fh; | ||
488 | |||
489 | err = videobuf_read_one(&chan->vidq, data, count, ppos, | ||
490 | file->f_flags & O_NONBLOCK); | ||
491 | unlock: | ||
492 | mutex_unlock(&dev->lock); | ||
493 | return err; | ||
855 | } | 494 | } |
856 | 495 | ||
857 | static unsigned int video_poll(struct file *file, | 496 | static unsigned int video_poll(struct file *file, |
858 | struct poll_table_struct *wait) | 497 | struct poll_table_struct *wait) |
859 | { | 498 | { |
860 | struct cx25821_fh *fh = file->private_data; | 499 | struct cx25821_channel *chan = video_drvdata(file); |
861 | struct cx25821_buffer *buf; | 500 | unsigned long req_events = poll_requested_events(wait); |
862 | 501 | unsigned int res = v4l2_ctrl_poll(file, wait); | |
863 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { | 502 | |
864 | /* streaming capture */ | 503 | if (req_events & (POLLIN | POLLRDNORM)) |
865 | if (list_empty(&fh->vidq.stream)) | 504 | res |= videobuf_poll_stream(file, &chan->vidq, wait); |
866 | return POLLERR; | 505 | return res; |
867 | buf = list_entry(fh->vidq.stream.next, | 506 | |
868 | struct cx25821_buffer, vb.stream); | 507 | /* This doesn't belong in poll(). This can be done |
869 | } else { | 508 | * much better with vb2. We keep this code here as a |
870 | /* read() capture */ | 509 | * reminder. |
871 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | 510 | if ((res & POLLIN) && buf->vb.state == VIDEOBUF_DONE) { |
872 | if (NULL == buf) | 511 | struct cx25821_dev *dev = chan->dev; |
873 | return POLLERR; | 512 | |
874 | } | 513 | if (dev && chan->use_cif_resolution) { |
875 | 514 | u8 cam_id = *((char *)buf->vb.baddr + 3); | |
876 | poll_wait(file, &buf->vb.done, wait); | 515 | memcpy((char *)buf->vb.baddr, |
877 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | 516 | (char *)buf->vb.baddr + (chan->width * 2), |
878 | if (buf->vb.state == VIDEOBUF_DONE) { | 517 | (chan->width * 2)); |
879 | struct cx25821_dev *dev = fh->dev; | 518 | *((char *)buf->vb.baddr + 3) = cam_id; |
880 | |||
881 | if (dev && dev->channels[fh->channel_id] | ||
882 | .use_cif_resolution) { | ||
883 | u8 cam_id = *((char *)buf->vb.baddr + 3); | ||
884 | memcpy((char *)buf->vb.baddr, | ||
885 | (char *)buf->vb.baddr + (fh->width * 2), | ||
886 | (fh->width * 2)); | ||
887 | *((char *)buf->vb.baddr + 3) = cam_id; | ||
888 | } | ||
889 | } | 519 | } |
890 | |||
891 | return POLLIN | POLLRDNORM; | ||
892 | } | 520 | } |
893 | 521 | */ | |
894 | return 0; | ||
895 | } | 522 | } |
896 | 523 | ||
897 | static int video_release(struct file *file) | 524 | static int video_release(struct file *file) |
898 | { | 525 | { |
899 | struct cx25821_fh *fh = file->private_data; | 526 | struct cx25821_channel *chan = video_drvdata(file); |
900 | struct cx25821_dev *dev = fh->dev; | 527 | struct v4l2_fh *fh = file->private_data; |
528 | struct cx25821_dev *dev = chan->dev; | ||
529 | const struct sram_channel *sram_ch = | ||
530 | dev->channels[0].sram_channels; | ||
901 | 531 | ||
532 | mutex_lock(&dev->lock); | ||
902 | /* stop the risc engine and fifo */ | 533 | /* stop the risc engine and fifo */ |
903 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ | 534 | cx_write(sram_ch->dma_ctl, 0); /* FIFO and RISC disable */ |
904 | 535 | ||
905 | /* stop video capture */ | 536 | /* stop video capture */ |
906 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { | 537 | if (chan->streaming_fh == fh) { |
907 | videobuf_queue_cancel(&fh->vidq); | 538 | videobuf_queue_cancel(&chan->vidq); |
908 | cx25821_res_free(dev, fh, RESOURCE_VIDEO0); | 539 | chan->streaming_fh = NULL; |
909 | } | 540 | } |
910 | 541 | ||
911 | if (fh->vidq.read_buf) { | 542 | if (chan->vidq.read_buf) { |
912 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); | 543 | cx25821_buffer_release(&chan->vidq, chan->vidq.read_buf); |
913 | kfree(fh->vidq.read_buf); | 544 | kfree(chan->vidq.read_buf); |
914 | } | 545 | } |
915 | 546 | ||
916 | videobuf_mmap_free(&fh->vidq); | 547 | videobuf_mmap_free(&chan->vidq); |
917 | 548 | mutex_unlock(&dev->lock); | |
918 | v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio); | ||
919 | file->private_data = NULL; | ||
920 | kfree(fh); | ||
921 | 549 | ||
922 | return 0; | 550 | return v4l2_fh_release(file); |
923 | } | 551 | } |
924 | 552 | ||
925 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 553 | /* VIDEO IOCTLS */ |
926 | { | ||
927 | struct cx25821_fh *fh = priv; | ||
928 | struct cx25821_dev *dev = fh->dev; | ||
929 | 554 | ||
930 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | 555 | static int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
556 | struct v4l2_fmtdesc *f) | ||
557 | { | ||
558 | if (unlikely(f->index >= ARRAY_SIZE(formats))) | ||
931 | return -EINVAL; | 559 | return -EINVAL; |
932 | 560 | ||
933 | if (unlikely(i != fh->type)) | 561 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); |
934 | return -EINVAL; | 562 | f->pixelformat = formats[f->index].fourcc; |
935 | 563 | ||
936 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, | 564 | return 0; |
937 | RESOURCE_VIDEO0)))) | 565 | } |
938 | return -EBUSY; | 566 | |
567 | static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
568 | struct v4l2_format *f) | ||
569 | { | ||
570 | struct cx25821_channel *chan = video_drvdata(file); | ||
571 | |||
572 | f->fmt.pix.width = chan->width; | ||
573 | f->fmt.pix.height = chan->height; | ||
574 | f->fmt.pix.field = chan->vidq.field; | ||
575 | f->fmt.pix.pixelformat = chan->fmt->fourcc; | ||
576 | f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3; | ||
577 | f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline; | ||
578 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
579 | f->fmt.pix.priv = 0; | ||
939 | 580 | ||
940 | return videobuf_streamon(get_queue(fh)); | 581 | return 0; |
941 | } | 582 | } |
942 | 583 | ||
943 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 584 | static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
585 | struct v4l2_format *f) | ||
944 | { | 586 | { |
945 | struct cx25821_fh *fh = priv; | 587 | struct cx25821_channel *chan = video_drvdata(file); |
946 | struct cx25821_dev *dev = fh->dev; | 588 | struct cx25821_dev *dev = chan->dev; |
947 | int err, res; | 589 | const struct cx25821_fmt *fmt; |
590 | enum v4l2_field field = f->fmt.pix.field; | ||
591 | unsigned int maxw, maxh; | ||
592 | unsigned w; | ||
948 | 593 | ||
949 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 594 | fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); |
950 | return -EINVAL; | 595 | if (NULL == fmt) |
951 | if (i != fh->type) | ||
952 | return -EINVAL; | 596 | return -EINVAL; |
597 | maxw = 720; | ||
598 | maxh = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480; | ||
599 | |||
600 | w = f->fmt.pix.width; | ||
601 | if (field != V4L2_FIELD_BOTTOM) | ||
602 | field = V4L2_FIELD_TOP; | ||
603 | if (w < 352) { | ||
604 | w = 176; | ||
605 | f->fmt.pix.height = maxh / 4; | ||
606 | } else if (w < 720) { | ||
607 | w = 352; | ||
608 | f->fmt.pix.height = maxh / 2; | ||
609 | } else { | ||
610 | w = 720; | ||
611 | f->fmt.pix.height = maxh; | ||
612 | field = V4L2_FIELD_INTERLACED; | ||
613 | } | ||
614 | f->fmt.pix.field = field; | ||
615 | f->fmt.pix.width = w; | ||
616 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
617 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
618 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
619 | f->fmt.pix.priv = 0; | ||
953 | 620 | ||
954 | res = cx25821_get_resource(fh, RESOURCE_VIDEO0); | ||
955 | err = videobuf_streamoff(get_queue(fh)); | ||
956 | if (err < 0) | ||
957 | return err; | ||
958 | cx25821_res_free(dev, fh, res); | ||
959 | return 0; | 621 | return 0; |
960 | } | 622 | } |
961 | 623 | ||
962 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 624 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
963 | struct v4l2_format *f) | 625 | struct v4l2_format *f) |
964 | { | 626 | { |
965 | struct cx25821_fh *fh = priv; | 627 | struct cx25821_channel *chan = video_drvdata(file); |
966 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 628 | struct cx25821_dev *dev = chan->dev; |
967 | struct v4l2_mbus_framefmt mbus_fmt; | ||
968 | int err; | ||
969 | int pix_format = PIXEL_FRMT_422; | 629 | int pix_format = PIXEL_FRMT_422; |
630 | int err; | ||
970 | 631 | ||
971 | if (fh) { | ||
972 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | ||
973 | fh->prio); | ||
974 | if (0 != err) | ||
975 | return err; | ||
976 | } | ||
977 | |||
978 | dprintk(2, "%s()\n", __func__); | ||
979 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); | 632 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
980 | 633 | ||
981 | if (0 != err) | 634 | if (0 != err) |
982 | return err; | 635 | return err; |
983 | 636 | ||
984 | fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); | 637 | chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); |
985 | fh->vidq.field = f->fmt.pix.field; | 638 | chan->vidq.field = f->fmt.pix.field; |
986 | 639 | chan->width = f->fmt.pix.width; | |
987 | /* check if width and height is valid based on set standard */ | 640 | chan->height = f->fmt.pix.height; |
988 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) | ||
989 | fh->width = f->fmt.pix.width; | ||
990 | |||
991 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) | ||
992 | fh->height = f->fmt.pix.height; | ||
993 | 641 | ||
994 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | 642 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) |
995 | pix_format = PIXEL_FRMT_411; | 643 | pix_format = PIXEL_FRMT_411; |
996 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | ||
997 | pix_format = PIXEL_FRMT_422; | ||
998 | else | 644 | else |
999 | return -EINVAL; | 645 | pix_format = PIXEL_FRMT_422; |
1000 | 646 | ||
1001 | cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); | 647 | cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); |
1002 | 648 | ||
1003 | /* check if cif resolution */ | 649 | /* check if cif resolution */ |
1004 | if (fh->width == 320 || fh->width == 352) | 650 | if (chan->width == 320 || chan->width == 352) |
1005 | dev->channels[fh->channel_id].use_cif_resolution = 1; | 651 | chan->use_cif_resolution = 1; |
1006 | else | 652 | else |
1007 | dev->channels[fh->channel_id].use_cif_resolution = 0; | 653 | chan->use_cif_resolution = 0; |
1008 | |||
1009 | dev->channels[fh->channel_id].cif_width = fh->width; | ||
1010 | medusa_set_resolution(dev, fh->width, SRAM_CH00); | ||
1011 | |||
1012 | dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width, | ||
1013 | fh->height, fh->vidq.field); | ||
1014 | v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); | ||
1015 | cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt); | ||
1016 | 654 | ||
655 | chan->cif_width = chan->width; | ||
656 | medusa_set_resolution(dev, chan->width, SRAM_CH00); | ||
1017 | return 0; | 657 | return 0; |
1018 | } | 658 | } |
1019 | 659 | ||
1020 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 660 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
1021 | { | 661 | { |
1022 | int ret_val = 0; | 662 | struct cx25821_channel *chan = video_drvdata(file); |
1023 | struct cx25821_fh *fh = priv; | ||
1024 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1025 | 663 | ||
1026 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | 664 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
665 | return -EINVAL; | ||
1027 | 666 | ||
1028 | p->sequence = dev->channels[fh->channel_id].vidq.count; | 667 | if (chan->streaming_fh && chan->streaming_fh != priv) |
668 | return -EBUSY; | ||
669 | chan->streaming_fh = priv; | ||
1029 | 670 | ||
1030 | return ret_val; | 671 | return videobuf_streamon(&chan->vidq); |
1031 | } | 672 | } |
1032 | 673 | ||
1033 | static int vidioc_log_status(struct file *file, void *priv) | 674 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
1034 | { | 675 | { |
1035 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 676 | struct cx25821_channel *chan = video_drvdata(file); |
1036 | struct cx25821_fh *fh = priv; | ||
1037 | char name[32 + 2]; | ||
1038 | 677 | ||
1039 | struct sram_channel *sram_ch = dev->channels[fh->channel_id] | 678 | if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1040 | .sram_channels; | 679 | return -EINVAL; |
1041 | u32 tmp = 0; | ||
1042 | |||
1043 | snprintf(name, sizeof(name), "%s/2", dev->name); | ||
1044 | pr_info("%s/2: ============ START LOG STATUS ============\n", | ||
1045 | dev->name); | ||
1046 | cx25821_call_all(dev, core, log_status); | ||
1047 | tmp = cx_read(sram_ch->dma_ctl); | ||
1048 | pr_info("Video input 0 is %s\n", | ||
1049 | (tmp & 0x11) ? "streaming" : "stopped"); | ||
1050 | pr_info("%s/2: ============= END LOG STATUS =============\n", | ||
1051 | dev->name); | ||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
1055 | static int vidioc_s_ctrl(struct file *file, void *priv, | ||
1056 | struct v4l2_control *ctl) | ||
1057 | { | ||
1058 | struct cx25821_fh *fh = priv; | ||
1059 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1060 | int err; | ||
1061 | 680 | ||
1062 | if (fh) { | 681 | if (chan->streaming_fh && chan->streaming_fh != priv) |
1063 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 682 | return -EBUSY; |
1064 | fh->prio); | 683 | if (chan->streaming_fh == NULL) |
1065 | if (0 != err) | 684 | return 0; |
1066 | return err; | ||
1067 | } | ||
1068 | 685 | ||
1069 | return cx25821_set_control(dev, ctl, fh->channel_id); | 686 | chan->streaming_fh = NULL; |
687 | return videobuf_streamoff(&chan->vidq); | ||
1070 | } | 688 | } |
1071 | 689 | ||
1072 | /* VIDEO IOCTLS */ | 690 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
1073 | int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
1074 | struct v4l2_format *f) | ||
1075 | { | 691 | { |
1076 | struct cx25821_fh *fh = priv; | 692 | int ret_val = 0; |
693 | struct cx25821_channel *chan = video_drvdata(file); | ||
1077 | 694 | ||
1078 | f->fmt.pix.width = fh->width; | 695 | ret_val = videobuf_dqbuf(&chan->vidq, p, file->f_flags & O_NONBLOCK); |
1079 | f->fmt.pix.height = fh->height; | 696 | p->sequence = chan->dma_vidq.count; |
1080 | f->fmt.pix.field = fh->vidq.field; | ||
1081 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | ||
1082 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; | ||
1083 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
1084 | 697 | ||
1085 | return 0; | 698 | return ret_val; |
1086 | } | 699 | } |
1087 | 700 | ||
1088 | int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 701 | static int vidioc_log_status(struct file *file, void *priv) |
1089 | struct v4l2_format *f) | ||
1090 | { | 702 | { |
1091 | struct cx25821_fmt *fmt; | 703 | struct cx25821_channel *chan = video_drvdata(file); |
1092 | enum v4l2_field field; | 704 | struct cx25821_dev *dev = chan->dev; |
1093 | unsigned int maxw, maxh; | 705 | const struct sram_channel *sram_ch = chan->sram_channels; |
1094 | 706 | u32 tmp = 0; | |
1095 | fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); | ||
1096 | if (NULL == fmt) | ||
1097 | return -EINVAL; | ||
1098 | |||
1099 | field = f->fmt.pix.field; | ||
1100 | maxw = 720; | ||
1101 | maxh = 576; | ||
1102 | |||
1103 | if (V4L2_FIELD_ANY == field) { | ||
1104 | if (f->fmt.pix.height > maxh / 2) | ||
1105 | field = V4L2_FIELD_INTERLACED; | ||
1106 | else | ||
1107 | field = V4L2_FIELD_TOP; | ||
1108 | } | ||
1109 | |||
1110 | switch (field) { | ||
1111 | case V4L2_FIELD_TOP: | ||
1112 | case V4L2_FIELD_BOTTOM: | ||
1113 | maxh = maxh / 2; | ||
1114 | break; | ||
1115 | case V4L2_FIELD_INTERLACED: | ||
1116 | break; | ||
1117 | default: | ||
1118 | return -EINVAL; | ||
1119 | } | ||
1120 | |||
1121 | f->fmt.pix.field = field; | ||
1122 | if (f->fmt.pix.height < 32) | ||
1123 | f->fmt.pix.height = 32; | ||
1124 | if (f->fmt.pix.height > maxh) | ||
1125 | f->fmt.pix.height = maxh; | ||
1126 | if (f->fmt.pix.width < 48) | ||
1127 | f->fmt.pix.width = 48; | ||
1128 | if (f->fmt.pix.width > maxw) | ||
1129 | f->fmt.pix.width = maxw; | ||
1130 | f->fmt.pix.width &= ~0x03; | ||
1131 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
1132 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
1133 | 707 | ||
708 | tmp = cx_read(sram_ch->dma_ctl); | ||
709 | pr_info("Video input 0 is %s\n", | ||
710 | (tmp & 0x11) ? "streaming" : "stopped"); | ||
1134 | return 0; | 711 | return 0; |
1135 | } | 712 | } |
1136 | 713 | ||
1137 | int cx25821_vidioc_querycap(struct file *file, void *priv, | 714 | |
715 | static int cx25821_vidioc_querycap(struct file *file, void *priv, | ||
1138 | struct v4l2_capability *cap) | 716 | struct v4l2_capability *cap) |
1139 | { | 717 | { |
1140 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 718 | struct cx25821_channel *chan = video_drvdata(file); |
719 | struct cx25821_dev *dev = chan->dev; | ||
720 | const u32 cap_input = V4L2_CAP_VIDEO_CAPTURE | | ||
721 | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | ||
722 | const u32 cap_output = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE; | ||
1141 | 723 | ||
1142 | strcpy(cap->driver, "cx25821"); | 724 | strcpy(cap->driver, "cx25821"); |
1143 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); | 725 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); |
1144 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); | 726 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); |
1145 | cap->version = CX25821_VERSION_CODE; | 727 | if (chan->id >= VID_CHANNEL_NUM) |
1146 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | | 728 | cap->device_caps = cap_output; |
1147 | V4L2_CAP_STREAMING; | 729 | else |
1148 | if (UNSET != dev->tuner_type) | 730 | cap->device_caps = cap_input; |
1149 | cap->capabilities |= V4L2_CAP_TUNER; | 731 | cap->capabilities = cap_input | cap_output | V4L2_CAP_DEVICE_CAPS; |
1150 | return 0; | ||
1151 | } | ||
1152 | |||
1153 | int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
1154 | struct v4l2_fmtdesc *f) | ||
1155 | { | ||
1156 | if (unlikely(f->index >= ARRAY_SIZE(formats))) | ||
1157 | return -EINVAL; | ||
1158 | |||
1159 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); | ||
1160 | f->pixelformat = formats[f->index].fourcc; | ||
1161 | |||
1162 | return 0; | 732 | return 0; |
1163 | } | 733 | } |
1164 | 734 | ||
1165 | int cx25821_vidioc_reqbufs(struct file *file, void *priv, | 735 | static int cx25821_vidioc_reqbufs(struct file *file, void *priv, |
1166 | struct v4l2_requestbuffers *p) | 736 | struct v4l2_requestbuffers *p) |
1167 | { | 737 | { |
1168 | struct cx25821_fh *fh = priv; | 738 | struct cx25821_channel *chan = video_drvdata(file); |
1169 | return videobuf_reqbufs(get_queue(fh), p); | 739 | |
740 | return videobuf_reqbufs(&chan->vidq, p); | ||
1170 | } | 741 | } |
1171 | 742 | ||
1172 | int cx25821_vidioc_querybuf(struct file *file, void *priv, | 743 | static int cx25821_vidioc_querybuf(struct file *file, void *priv, |
1173 | struct v4l2_buffer *p) | 744 | struct v4l2_buffer *p) |
1174 | { | 745 | { |
1175 | struct cx25821_fh *fh = priv; | 746 | struct cx25821_channel *chan = video_drvdata(file); |
1176 | return videobuf_querybuf(get_queue(fh), p); | ||
1177 | } | ||
1178 | 747 | ||
1179 | int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 748 | return videobuf_querybuf(&chan->vidq, p); |
1180 | { | ||
1181 | struct cx25821_fh *fh = priv; | ||
1182 | return videobuf_qbuf(get_queue(fh), p); | ||
1183 | } | 749 | } |
1184 | 750 | ||
1185 | int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) | 751 | static int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
1186 | { | 752 | { |
1187 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | 753 | struct cx25821_channel *chan = video_drvdata(file); |
1188 | struct cx25821_fh *fh = f; | ||
1189 | |||
1190 | *p = v4l2_prio_max(&dev->channels[fh->channel_id].prio); | ||
1191 | 754 | ||
1192 | return 0; | 755 | return videobuf_qbuf(&chan->vidq, p); |
1193 | } | 756 | } |
1194 | 757 | ||
1195 | int cx25821_vidioc_s_priority(struct file *file, void *f, | 758 | static int cx25821_vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorms) |
1196 | enum v4l2_priority prio) | ||
1197 | { | 759 | { |
1198 | struct cx25821_fh *fh = f; | 760 | struct cx25821_channel *chan = video_drvdata(file); |
1199 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | ||
1200 | 761 | ||
1201 | return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio, | 762 | *tvnorms = chan->dev->tvnorm; |
1202 | prio); | 763 | return 0; |
1203 | } | 764 | } |
1204 | 765 | ||
1205 | #ifdef TUNER_FLAG | ||
1206 | int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms) | 766 | int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms) |
1207 | { | 767 | { |
1208 | struct cx25821_fh *fh = priv; | 768 | struct cx25821_channel *chan = video_drvdata(file); |
1209 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 769 | struct cx25821_dev *dev = chan->dev; |
1210 | int err; | ||
1211 | |||
1212 | dprintk(1, "%s()\n", __func__); | ||
1213 | |||
1214 | if (fh) { | ||
1215 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | ||
1216 | fh->prio); | ||
1217 | if (0 != err) | ||
1218 | return err; | ||
1219 | } | ||
1220 | 770 | ||
1221 | if (dev->tvnorm == tvnorms) | 771 | if (dev->tvnorm == tvnorms) |
1222 | return 0; | 772 | return 0; |
1223 | 773 | ||
1224 | mutex_lock(&dev->lock); | 774 | dev->tvnorm = tvnorms; |
1225 | cx25821_set_tvnorm(dev, tvnorms); | 775 | chan->width = 720; |
1226 | mutex_unlock(&dev->lock); | 776 | chan->height = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480; |
1227 | 777 | ||
1228 | medusa_set_videostandard(dev); | 778 | medusa_set_videostandard(dev); |
1229 | 779 | ||
1230 | return 0; | 780 | return 0; |
1231 | } | 781 | } |
1232 | #endif | ||
1233 | 782 | ||
1234 | int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) | 783 | static int cx25821_vidioc_enum_input(struct file *file, void *priv, |
784 | struct v4l2_input *i) | ||
1235 | { | 785 | { |
1236 | static const char * const iname[] = { | 786 | if (i->index) |
1237 | [CX25821_VMUX_COMPOSITE] = "Composite", | ||
1238 | [CX25821_VMUX_SVIDEO] = "S-Video", | ||
1239 | [CX25821_VMUX_DEBUG] = "for debug only", | ||
1240 | }; | ||
1241 | unsigned int n; | ||
1242 | dprintk(1, "%s()\n", __func__); | ||
1243 | |||
1244 | n = i->index; | ||
1245 | if (n >= 2) | ||
1246 | return -EINVAL; | ||
1247 | |||
1248 | if (0 == INPUT(n)->type) | ||
1249 | return -EINVAL; | 787 | return -EINVAL; |
1250 | 788 | ||
1251 | i->type = V4L2_INPUT_TYPE_CAMERA; | 789 | i->type = V4L2_INPUT_TYPE_CAMERA; |
1252 | strcpy(i->name, iname[INPUT(n)->type]); | ||
1253 | |||
1254 | i->std = CX25821_NORMS; | 790 | i->std = CX25821_NORMS; |
791 | strcpy(i->name, "Composite"); | ||
1255 | return 0; | 792 | return 0; |
1256 | } | 793 | } |
1257 | 794 | ||
1258 | int cx25821_vidioc_enum_input(struct file *file, void *priv, | 795 | static int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1259 | struct v4l2_input *i) | ||
1260 | { | ||
1261 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1262 | dprintk(1, "%s()\n", __func__); | ||
1263 | return cx25821_enum_input(dev, i); | ||
1264 | } | ||
1265 | |||
1266 | int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i) | ||
1267 | { | ||
1268 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1269 | |||
1270 | *i = dev->input; | ||
1271 | dprintk(1, "%s(): returns %d\n", __func__, *i); | ||
1272 | return 0; | ||
1273 | } | ||
1274 | |||
1275 | int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
1276 | { | ||
1277 | struct cx25821_fh *fh = priv; | ||
1278 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1279 | int err; | ||
1280 | |||
1281 | dprintk(1, "%s(%d)\n", __func__, i); | ||
1282 | |||
1283 | if (fh) { | ||
1284 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | ||
1285 | fh->prio); | ||
1286 | if (0 != err) | ||
1287 | return err; | ||
1288 | } | ||
1289 | |||
1290 | if (i >= CX25821_NR_INPUT) { | ||
1291 | dprintk(1, "%s(): -EINVAL\n", __func__); | ||
1292 | return -EINVAL; | ||
1293 | } | ||
1294 | |||
1295 | mutex_lock(&dev->lock); | ||
1296 | cx25821_video_mux(dev, i); | ||
1297 | mutex_unlock(&dev->lock); | ||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | #ifdef TUNER_FLAG | ||
1302 | int cx25821_vidioc_g_frequency(struct file *file, void *priv, | ||
1303 | struct v4l2_frequency *f) | ||
1304 | { | ||
1305 | struct cx25821_fh *fh = priv; | ||
1306 | struct cx25821_dev *dev = fh->dev; | ||
1307 | |||
1308 | f->frequency = dev->freq; | ||
1309 | |||
1310 | cx25821_call_all(dev, tuner, g_frequency, f); | ||
1311 | |||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | int cx25821_set_freq(struct cx25821_dev *dev, const struct v4l2_frequency *f) | ||
1316 | { | ||
1317 | mutex_lock(&dev->lock); | ||
1318 | dev->freq = f->frequency; | ||
1319 | |||
1320 | cx25821_call_all(dev, tuner, s_frequency, f); | ||
1321 | |||
1322 | /* When changing channels it is required to reset TVAUDIO */ | ||
1323 | msleep(10); | ||
1324 | |||
1325 | mutex_unlock(&dev->lock); | ||
1326 | |||
1327 | return 0; | ||
1328 | } | ||
1329 | |||
1330 | int cx25821_vidioc_s_frequency(struct file *file, void *priv, | ||
1331 | const struct v4l2_frequency *f) | ||
1332 | { | ||
1333 | struct cx25821_fh *fh = priv; | ||
1334 | struct cx25821_dev *dev; | ||
1335 | int err; | ||
1336 | |||
1337 | if (fh) { | ||
1338 | dev = fh->dev; | ||
1339 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | ||
1340 | fh->prio); | ||
1341 | if (0 != err) | ||
1342 | return err; | ||
1343 | } else { | ||
1344 | pr_err("Invalid fh pointer!\n"); | ||
1345 | return -EINVAL; | ||
1346 | } | ||
1347 | |||
1348 | return cx25821_set_freq(dev, f); | ||
1349 | } | ||
1350 | #endif | ||
1351 | |||
1352 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1353 | int cx25821_vidioc_g_register(struct file *file, void *fh, | ||
1354 | struct v4l2_dbg_register *reg) | ||
1355 | { | ||
1356 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | ||
1357 | |||
1358 | if (!v4l2_chip_match_host(®->match)) | ||
1359 | return -EINVAL; | ||
1360 | |||
1361 | cx25821_call_all(dev, core, g_register, reg); | ||
1362 | |||
1363 | return 0; | ||
1364 | } | ||
1365 | |||
1366 | int cx25821_vidioc_s_register(struct file *file, void *fh, | ||
1367 | const struct v4l2_dbg_register *reg) | ||
1368 | { | ||
1369 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | ||
1370 | |||
1371 | if (!v4l2_chip_match_host(®->match)) | ||
1372 | return -EINVAL; | ||
1373 | |||
1374 | cx25821_call_all(dev, core, s_register, reg); | ||
1375 | |||
1376 | return 0; | ||
1377 | } | ||
1378 | |||
1379 | #endif | ||
1380 | |||
1381 | #ifdef TUNER_FLAG | ||
1382 | int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | ||
1383 | { | ||
1384 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1385 | |||
1386 | if (unlikely(UNSET == dev->tuner_type)) | ||
1387 | return -EINVAL; | ||
1388 | if (0 != t->index) | ||
1389 | return -EINVAL; | ||
1390 | |||
1391 | strcpy(t->name, "Television"); | ||
1392 | t->type = V4L2_TUNER_ANALOG_TV; | ||
1393 | t->capability = V4L2_TUNER_CAP_NORM; | ||
1394 | t->rangehigh = 0xffffffffUL; | ||
1395 | |||
1396 | t->signal = 0xffff; /* LOCKED */ | ||
1397 | return 0; | ||
1398 | } | ||
1399 | |||
1400 | int cx25821_vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *t) | ||
1401 | { | ||
1402 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1403 | struct cx25821_fh *fh = priv; | ||
1404 | int err; | ||
1405 | |||
1406 | if (fh) { | ||
1407 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | ||
1408 | fh->prio); | ||
1409 | if (0 != err) | ||
1410 | return err; | ||
1411 | } | ||
1412 | |||
1413 | dprintk(1, "%s()\n", __func__); | ||
1414 | if (UNSET == dev->tuner_type) | ||
1415 | return -EINVAL; | ||
1416 | if (0 != t->index) | ||
1417 | return -EINVAL; | ||
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | #endif | ||
1423 | /*****************************************************************************/ | ||
1424 | static const struct v4l2_queryctrl no_ctl = { | ||
1425 | .name = "42", | ||
1426 | .flags = V4L2_CTRL_FLAG_DISABLED, | ||
1427 | }; | ||
1428 | |||
1429 | static struct v4l2_queryctrl cx25821_ctls[] = { | ||
1430 | /* --- video --- */ | ||
1431 | { | ||
1432 | .id = V4L2_CID_BRIGHTNESS, | ||
1433 | .name = "Brightness", | ||
1434 | .minimum = 0, | ||
1435 | .maximum = 10000, | ||
1436 | .step = 1, | ||
1437 | .default_value = 6200, | ||
1438 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1439 | }, { | ||
1440 | .id = V4L2_CID_CONTRAST, | ||
1441 | .name = "Contrast", | ||
1442 | .minimum = 0, | ||
1443 | .maximum = 10000, | ||
1444 | .step = 1, | ||
1445 | .default_value = 5000, | ||
1446 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1447 | }, { | ||
1448 | .id = V4L2_CID_SATURATION, | ||
1449 | .name = "Saturation", | ||
1450 | .minimum = 0, | ||
1451 | .maximum = 10000, | ||
1452 | .step = 1, | ||
1453 | .default_value = 5000, | ||
1454 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1455 | }, { | ||
1456 | .id = V4L2_CID_HUE, | ||
1457 | .name = "Hue", | ||
1458 | .minimum = 0, | ||
1459 | .maximum = 10000, | ||
1460 | .step = 1, | ||
1461 | .default_value = 5000, | ||
1462 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1463 | } | ||
1464 | }; | ||
1465 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); | ||
1466 | |||
1467 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | ||
1468 | { | 796 | { |
1469 | int i; | 797 | *i = 0; |
1470 | |||
1471 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | ||
1472 | return -EINVAL; | ||
1473 | for (i = 0; i < CX25821_CTLS; i++) | ||
1474 | if (cx25821_ctls[i].id == qctrl->id) | ||
1475 | break; | ||
1476 | if (i == CX25821_CTLS) { | ||
1477 | *qctrl = no_ctl; | ||
1478 | return 0; | ||
1479 | } | ||
1480 | *qctrl = cx25821_ctls[i]; | ||
1481 | return 0; | 798 | return 0; |
1482 | } | 799 | } |
1483 | 800 | ||
1484 | int cx25821_vidioc_queryctrl(struct file *file, void *priv, | 801 | static int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) |
1485 | struct v4l2_queryctrl *qctrl) | ||
1486 | { | ||
1487 | return cx25821_ctrl_query(qctrl); | ||
1488 | } | ||
1489 | |||
1490 | /* ------------------------------------------------------------------ */ | ||
1491 | /* VIDEO CTRL IOCTLS */ | ||
1492 | |||
1493 | static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) | ||
1494 | { | 802 | { |
1495 | unsigned int i; | 803 | return i ? -EINVAL : 0; |
1496 | |||
1497 | for (i = 0; i < CX25821_CTLS; i++) | ||
1498 | if (cx25821_ctls[i].id == id) | ||
1499 | return cx25821_ctls + i; | ||
1500 | return NULL; | ||
1501 | } | 804 | } |
1502 | 805 | ||
1503 | int cx25821_vidioc_g_ctrl(struct file *file, void *priv, | 806 | static int cx25821_s_ctrl(struct v4l2_ctrl *ctrl) |
1504 | struct v4l2_control *ctl) | ||
1505 | { | 807 | { |
1506 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 808 | struct cx25821_channel *chan = |
1507 | struct cx25821_fh *fh = priv; | 809 | container_of(ctrl->handler, struct cx25821_channel, hdl); |
810 | struct cx25821_dev *dev = chan->dev; | ||
1508 | 811 | ||
1509 | const struct v4l2_queryctrl *ctrl; | 812 | switch (ctrl->id) { |
1510 | |||
1511 | ctrl = ctrl_by_id(ctl->id); | ||
1512 | |||
1513 | if (NULL == ctrl) | ||
1514 | return -EINVAL; | ||
1515 | switch (ctl->id) { | ||
1516 | case V4L2_CID_BRIGHTNESS: | 813 | case V4L2_CID_BRIGHTNESS: |
1517 | ctl->value = dev->channels[fh->channel_id].ctl_bright; | 814 | medusa_set_brightness(dev, ctrl->val, chan->id); |
1518 | break; | 815 | break; |
1519 | case V4L2_CID_HUE: | 816 | case V4L2_CID_HUE: |
1520 | ctl->value = dev->channels[fh->channel_id].ctl_hue; | 817 | medusa_set_hue(dev, ctrl->val, chan->id); |
1521 | break; | 818 | break; |
1522 | case V4L2_CID_CONTRAST: | 819 | case V4L2_CID_CONTRAST: |
1523 | ctl->value = dev->channels[fh->channel_id].ctl_contrast; | 820 | medusa_set_contrast(dev, ctrl->val, chan->id); |
1524 | break; | 821 | break; |
1525 | case V4L2_CID_SATURATION: | 822 | case V4L2_CID_SATURATION: |
1526 | ctl->value = dev->channels[fh->channel_id].ctl_saturation; | 823 | medusa_set_saturation(dev, ctrl->val, chan->id); |
1527 | break; | ||
1528 | } | ||
1529 | return 0; | ||
1530 | } | ||
1531 | |||
1532 | int cx25821_set_control(struct cx25821_dev *dev, | ||
1533 | struct v4l2_control *ctl, int chan_num) | ||
1534 | { | ||
1535 | int err; | ||
1536 | const struct v4l2_queryctrl *ctrl; | ||
1537 | |||
1538 | err = -EINVAL; | ||
1539 | |||
1540 | ctrl = ctrl_by_id(ctl->id); | ||
1541 | |||
1542 | if (NULL == ctrl) | ||
1543 | return err; | ||
1544 | |||
1545 | switch (ctrl->type) { | ||
1546 | case V4L2_CTRL_TYPE_BOOLEAN: | ||
1547 | case V4L2_CTRL_TYPE_MENU: | ||
1548 | case V4L2_CTRL_TYPE_INTEGER: | ||
1549 | if (ctl->value < ctrl->minimum) | ||
1550 | ctl->value = ctrl->minimum; | ||
1551 | if (ctl->value > ctrl->maximum) | ||
1552 | ctl->value = ctrl->maximum; | ||
1553 | break; | 824 | break; |
1554 | default: | 825 | default: |
1555 | /* nothing */ ; | ||
1556 | } | ||
1557 | |||
1558 | switch (ctl->id) { | ||
1559 | case V4L2_CID_BRIGHTNESS: | ||
1560 | dev->channels[chan_num].ctl_bright = ctl->value; | ||
1561 | medusa_set_brightness(dev, ctl->value, chan_num); | ||
1562 | break; | ||
1563 | case V4L2_CID_HUE: | ||
1564 | dev->channels[chan_num].ctl_hue = ctl->value; | ||
1565 | medusa_set_hue(dev, ctl->value, chan_num); | ||
1566 | break; | ||
1567 | case V4L2_CID_CONTRAST: | ||
1568 | dev->channels[chan_num].ctl_contrast = ctl->value; | ||
1569 | medusa_set_contrast(dev, ctl->value, chan_num); | ||
1570 | break; | ||
1571 | case V4L2_CID_SATURATION: | ||
1572 | dev->channels[chan_num].ctl_saturation = ctl->value; | ||
1573 | medusa_set_saturation(dev, ctl->value, chan_num); | ||
1574 | break; | ||
1575 | } | ||
1576 | |||
1577 | err = 0; | ||
1578 | |||
1579 | return err; | ||
1580 | } | ||
1581 | |||
1582 | static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num) | ||
1583 | { | ||
1584 | struct v4l2_control ctrl; | ||
1585 | int i; | ||
1586 | for (i = 0; i < CX25821_CTLS; i++) { | ||
1587 | ctrl.id = cx25821_ctls[i].id; | ||
1588 | ctrl.value = cx25821_ctls[i].default_value; | ||
1589 | |||
1590 | cx25821_set_control(dev, &ctrl, chan_num); | ||
1591 | } | ||
1592 | } | ||
1593 | |||
1594 | int cx25821_vidioc_cropcap(struct file *file, void *priv, | ||
1595 | struct v4l2_cropcap *cropcap) | ||
1596 | { | ||
1597 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1598 | |||
1599 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1600 | return -EINVAL; | 826 | return -EINVAL; |
1601 | cropcap->bounds.top = 0; | ||
1602 | cropcap->bounds.left = 0; | ||
1603 | cropcap->bounds.width = 720; | ||
1604 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; | ||
1605 | cropcap->pixelaspect.numerator = | ||
1606 | dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; | ||
1607 | cropcap->pixelaspect.denominator = | ||
1608 | dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; | ||
1609 | cropcap->defrect = cropcap->bounds; | ||
1610 | return 0; | ||
1611 | } | ||
1612 | |||
1613 | int cx25821_vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) | ||
1614 | { | ||
1615 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | ||
1616 | struct cx25821_fh *fh = priv; | ||
1617 | int err; | ||
1618 | |||
1619 | if (fh) { | ||
1620 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | ||
1621 | fh->prio); | ||
1622 | if (0 != err) | ||
1623 | return err; | ||
1624 | } | 827 | } |
1625 | /* cx25821_vidioc_s_crop not supported */ | 828 | return 0; |
1626 | return -EINVAL; | ||
1627 | } | ||
1628 | |||
1629 | int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) | ||
1630 | { | ||
1631 | /* cx25821_vidioc_g_crop not supported */ | ||
1632 | return -EINVAL; | ||
1633 | } | 829 | } |
1634 | 830 | ||
1635 | int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) | 831 | static int cx25821_vidioc_enum_output(struct file *file, void *priv, |
832 | struct v4l2_output *o) | ||
1636 | { | 833 | { |
1637 | /* medusa does not support video standard sensing of current input */ | 834 | if (o->index) |
1638 | *norm = CX25821_NORMS; | 835 | return -EINVAL; |
1639 | 836 | ||
837 | o->type = V4L2_INPUT_TYPE_CAMERA; | ||
838 | o->std = CX25821_NORMS; | ||
839 | strcpy(o->name, "Composite"); | ||
1640 | return 0; | 840 | return 0; |
1641 | } | 841 | } |
1642 | 842 | ||
1643 | int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm) | 843 | static int cx25821_vidioc_g_output(struct file *file, void *priv, unsigned int *o) |
1644 | { | 844 | { |
1645 | if (tvnorm == V4L2_STD_PAL_BG) { | 845 | *o = 0; |
1646 | if (width == 352 || width == 720) | ||
1647 | return 1; | ||
1648 | else | ||
1649 | return 0; | ||
1650 | } | ||
1651 | |||
1652 | if (tvnorm == V4L2_STD_NTSC_M) { | ||
1653 | if (width == 320 || width == 352 || width == 720) | ||
1654 | return 1; | ||
1655 | else | ||
1656 | return 0; | ||
1657 | } | ||
1658 | return 0; | 846 | return 0; |
1659 | } | 847 | } |
1660 | 848 | ||
1661 | int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm) | 849 | static int cx25821_vidioc_s_output(struct file *file, void *priv, unsigned int o) |
1662 | { | 850 | { |
1663 | if (tvnorm == V4L2_STD_PAL_BG) { | 851 | return o ? -EINVAL : 0; |
1664 | if (height == 576 || height == 288) | ||
1665 | return 1; | ||
1666 | else | ||
1667 | return 0; | ||
1668 | } | ||
1669 | |||
1670 | if (tvnorm == V4L2_STD_NTSC_M) { | ||
1671 | if (height == 480 || height == 240) | ||
1672 | return 1; | ||
1673 | else | ||
1674 | return 0; | ||
1675 | } | ||
1676 | |||
1677 | return 0; | ||
1678 | } | 852 | } |
1679 | 853 | ||
1680 | static long video_ioctl_upstream9(struct file *file, unsigned int cmd, | 854 | static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv, |
1681 | unsigned long arg) | 855 | struct v4l2_format *f) |
1682 | { | 856 | { |
1683 | struct cx25821_fh *fh = file->private_data; | 857 | struct cx25821_channel *chan = video_drvdata(file); |
1684 | struct cx25821_dev *dev = fh->dev; | 858 | struct cx25821_dev *dev = chan->dev; |
1685 | int command = 0; | 859 | const struct cx25821_fmt *fmt; |
1686 | struct upstream_user_struct *data_from_user; | ||
1687 | |||
1688 | data_from_user = (struct upstream_user_struct *)arg; | ||
1689 | |||
1690 | if (!data_from_user) { | ||
1691 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); | ||
1692 | return 0; | ||
1693 | } | ||
1694 | |||
1695 | command = data_from_user->command; | ||
1696 | |||
1697 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) | ||
1698 | return 0; | ||
1699 | |||
1700 | dev->input_filename = data_from_user->input_filename; | ||
1701 | dev->input_audiofilename = data_from_user->input_filename; | ||
1702 | dev->vid_stdname = data_from_user->vid_stdname; | ||
1703 | dev->pixel_format = data_from_user->pixel_format; | ||
1704 | dev->channel_select = data_from_user->channel_select; | ||
1705 | dev->command = data_from_user->command; | ||
1706 | |||
1707 | switch (command) { | ||
1708 | case UPSTREAM_START_VIDEO: | ||
1709 | cx25821_start_upstream_video_ch1(dev, data_from_user); | ||
1710 | break; | ||
1711 | |||
1712 | case UPSTREAM_STOP_VIDEO: | ||
1713 | cx25821_stop_upstream_video_ch1(dev); | ||
1714 | break; | ||
1715 | } | ||
1716 | 860 | ||
861 | fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); | ||
862 | if (NULL == fmt) | ||
863 | return -EINVAL; | ||
864 | f->fmt.pix.width = 720; | ||
865 | f->fmt.pix.height = (dev->tvnorm & V4L2_STD_625_50) ? 576 : 480; | ||
866 | f->fmt.pix.field = V4L2_FIELD_INTERLACED; | ||
867 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
868 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
869 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
870 | f->fmt.pix.priv = 0; | ||
1717 | return 0; | 871 | return 0; |
1718 | } | 872 | } |
1719 | 873 | ||
1720 | static long video_ioctl_upstream10(struct file *file, unsigned int cmd, | 874 | static int vidioc_s_fmt_vid_out(struct file *file, void *priv, |
1721 | unsigned long arg) | 875 | struct v4l2_format *f) |
1722 | { | 876 | { |
1723 | struct cx25821_fh *fh = file->private_data; | 877 | struct cx25821_channel *chan = video_drvdata(file); |
1724 | struct cx25821_dev *dev = fh->dev; | 878 | int err; |
1725 | int command = 0; | ||
1726 | struct upstream_user_struct *data_from_user; | ||
1727 | |||
1728 | data_from_user = (struct upstream_user_struct *)arg; | ||
1729 | |||
1730 | if (!data_from_user) { | ||
1731 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); | ||
1732 | return 0; | ||
1733 | } | ||
1734 | |||
1735 | command = data_from_user->command; | ||
1736 | |||
1737 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) | ||
1738 | return 0; | ||
1739 | |||
1740 | dev->input_filename_ch2 = data_from_user->input_filename; | ||
1741 | dev->input_audiofilename = data_from_user->input_filename; | ||
1742 | dev->vid_stdname_ch2 = data_from_user->vid_stdname; | ||
1743 | dev->pixel_format_ch2 = data_from_user->pixel_format; | ||
1744 | dev->channel_select_ch2 = data_from_user->channel_select; | ||
1745 | dev->command_ch2 = data_from_user->command; | ||
1746 | 879 | ||
1747 | switch (command) { | 880 | err = cx25821_vidioc_try_fmt_vid_out(file, priv, f); |
1748 | case UPSTREAM_START_VIDEO: | ||
1749 | cx25821_start_upstream_video_ch2(dev, data_from_user); | ||
1750 | break; | ||
1751 | 881 | ||
1752 | case UPSTREAM_STOP_VIDEO: | 882 | if (0 != err) |
1753 | cx25821_stop_upstream_video_ch2(dev); | 883 | return err; |
1754 | break; | ||
1755 | } | ||
1756 | 884 | ||
885 | chan->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); | ||
886 | chan->vidq.field = f->fmt.pix.field; | ||
887 | chan->width = f->fmt.pix.width; | ||
888 | chan->height = f->fmt.pix.height; | ||
889 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | ||
890 | chan->pixel_formats = PIXEL_FRMT_411; | ||
891 | else | ||
892 | chan->pixel_formats = PIXEL_FRMT_422; | ||
1757 | return 0; | 893 | return 0; |
1758 | } | 894 | } |
1759 | 895 | ||
1760 | static long video_ioctl_upstream11(struct file *file, unsigned int cmd, | 896 | static ssize_t video_write(struct file *file, const char __user *data, size_t count, |
1761 | unsigned long arg) | 897 | loff_t *ppos) |
1762 | { | 898 | { |
1763 | struct cx25821_fh *fh = file->private_data; | 899 | struct cx25821_channel *chan = video_drvdata(file); |
1764 | struct cx25821_dev *dev = fh->dev; | 900 | struct cx25821_dev *dev = chan->dev; |
1765 | int command = 0; | 901 | struct v4l2_fh *fh = file->private_data; |
1766 | struct upstream_user_struct *data_from_user; | 902 | int err = 0; |
1767 | |||
1768 | data_from_user = (struct upstream_user_struct *)arg; | ||
1769 | 903 | ||
1770 | if (!data_from_user) { | 904 | if (mutex_lock_interruptible(&dev->lock)) |
1771 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); | 905 | return -ERESTARTSYS; |
1772 | return 0; | 906 | if (chan->streaming_fh && chan->streaming_fh != fh) { |
907 | err = -EBUSY; | ||
908 | goto unlock; | ||
1773 | } | 909 | } |
1774 | 910 | if (!chan->streaming_fh) { | |
1775 | command = data_from_user->command; | 911 | err = cx25821_vidupstream_init(chan, chan->pixel_formats); |
1776 | 912 | if (err) | |
1777 | if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) | 913 | goto unlock; |
1778 | return 0; | 914 | chan->streaming_fh = fh; |
1779 | |||
1780 | dev->input_filename = data_from_user->input_filename; | ||
1781 | dev->input_audiofilename = data_from_user->input_filename; | ||
1782 | dev->vid_stdname = data_from_user->vid_stdname; | ||
1783 | dev->pixel_format = data_from_user->pixel_format; | ||
1784 | dev->channel_select = data_from_user->channel_select; | ||
1785 | dev->command = data_from_user->command; | ||
1786 | |||
1787 | switch (command) { | ||
1788 | case UPSTREAM_START_AUDIO: | ||
1789 | cx25821_start_upstream_audio(dev, data_from_user); | ||
1790 | break; | ||
1791 | |||
1792 | case UPSTREAM_STOP_AUDIO: | ||
1793 | cx25821_stop_upstream_audio(dev); | ||
1794 | break; | ||
1795 | } | 915 | } |
1796 | 916 | ||
1797 | return 0; | 917 | err = cx25821_write_frame(chan, data, count); |
918 | count -= err; | ||
919 | *ppos += err; | ||
920 | |||
921 | unlock: | ||
922 | mutex_unlock(&dev->lock); | ||
923 | return err; | ||
1798 | } | 924 | } |
1799 | 925 | ||
1800 | static long video_ioctl_set(struct file *file, unsigned int cmd, | 926 | static int video_out_release(struct file *file) |
1801 | unsigned long arg) | ||
1802 | { | 927 | { |
1803 | struct cx25821_fh *fh = file->private_data; | 928 | struct cx25821_channel *chan = video_drvdata(file); |
1804 | struct cx25821_dev *dev = fh->dev; | 929 | struct cx25821_dev *dev = chan->dev; |
1805 | struct downstream_user_struct *data_from_user; | 930 | struct v4l2_fh *fh = file->private_data; |
1806 | int command; | ||
1807 | int width = 720; | ||
1808 | int selected_channel = 0; | ||
1809 | int pix_format = 0; | ||
1810 | int i = 0; | ||
1811 | int cif_enable = 0; | ||
1812 | int cif_width = 0; | ||
1813 | |||
1814 | data_from_user = (struct downstream_user_struct *)arg; | ||
1815 | |||
1816 | if (!data_from_user) { | ||
1817 | pr_err("%s(): User data is INVALID. Returning\n", __func__); | ||
1818 | return 0; | ||
1819 | } | ||
1820 | |||
1821 | command = data_from_user->command; | ||
1822 | |||
1823 | if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT | ||
1824 | && command != ENABLE_CIF_RESOLUTION && command != REG_READ | ||
1825 | && command != REG_WRITE && command != MEDUSA_READ | ||
1826 | && command != MEDUSA_WRITE) { | ||
1827 | return 0; | ||
1828 | } | ||
1829 | |||
1830 | switch (command) { | ||
1831 | case SET_VIDEO_STD: | ||
1832 | if (!strcmp(data_from_user->vid_stdname, "PAL")) | ||
1833 | dev->tvnorm = V4L2_STD_PAL_BG; | ||
1834 | else | ||
1835 | dev->tvnorm = V4L2_STD_NTSC_M; | ||
1836 | medusa_set_videostandard(dev); | ||
1837 | break; | ||
1838 | |||
1839 | case SET_PIXEL_FORMAT: | ||
1840 | selected_channel = data_from_user->decoder_select; | ||
1841 | pix_format = data_from_user->pixel_format; | ||
1842 | |||
1843 | if (!(selected_channel <= 7 && selected_channel >= 0)) { | ||
1844 | selected_channel -= 4; | ||
1845 | selected_channel = selected_channel % 8; | ||
1846 | } | ||
1847 | |||
1848 | if (selected_channel >= 0) | ||
1849 | cx25821_set_pixel_format(dev, selected_channel, | ||
1850 | pix_format); | ||
1851 | |||
1852 | break; | ||
1853 | |||
1854 | case ENABLE_CIF_RESOLUTION: | ||
1855 | selected_channel = data_from_user->decoder_select; | ||
1856 | cif_enable = data_from_user->cif_resolution_enable; | ||
1857 | cif_width = data_from_user->cif_width; | ||
1858 | |||
1859 | if (cif_enable) { | ||
1860 | if (dev->tvnorm & V4L2_STD_PAL_BG | ||
1861 | || dev->tvnorm & V4L2_STD_PAL_DK) { | ||
1862 | width = 352; | ||
1863 | } else { | ||
1864 | width = cif_width; | ||
1865 | if (cif_width != 320 && cif_width != 352) | ||
1866 | width = 320; | ||
1867 | } | ||
1868 | } | ||
1869 | |||
1870 | if (!(selected_channel <= 7 && selected_channel >= 0)) { | ||
1871 | selected_channel -= 4; | ||
1872 | selected_channel = selected_channel % 8; | ||
1873 | } | ||
1874 | |||
1875 | if (selected_channel <= 7 && selected_channel >= 0) { | ||
1876 | dev->channels[selected_channel].use_cif_resolution = | ||
1877 | cif_enable; | ||
1878 | dev->channels[selected_channel].cif_width = width; | ||
1879 | } else { | ||
1880 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | ||
1881 | dev->channels[i].use_cif_resolution = | ||
1882 | cif_enable; | ||
1883 | dev->channels[i].cif_width = width; | ||
1884 | } | ||
1885 | } | ||
1886 | 931 | ||
1887 | medusa_set_resolution(dev, width, selected_channel); | 932 | mutex_lock(&dev->lock); |
1888 | break; | 933 | if (chan->streaming_fh == fh) { |
1889 | case REG_READ: | 934 | cx25821_stop_upstream_video(chan); |
1890 | data_from_user->reg_data = cx_read(data_from_user->reg_address); | 935 | chan->streaming_fh = NULL; |
1891 | break; | ||
1892 | case REG_WRITE: | ||
1893 | cx_write(data_from_user->reg_address, data_from_user->reg_data); | ||
1894 | break; | ||
1895 | case MEDUSA_READ: | ||
1896 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
1897 | (u16) data_from_user->reg_address, | ||
1898 | &data_from_user->reg_data); | ||
1899 | break; | ||
1900 | case MEDUSA_WRITE: | ||
1901 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
1902 | (u16) data_from_user->reg_address, | ||
1903 | data_from_user->reg_data); | ||
1904 | break; | ||
1905 | } | 936 | } |
937 | mutex_unlock(&dev->lock); | ||
1906 | 938 | ||
1907 | return 0; | 939 | return v4l2_fh_release(file); |
1908 | } | 940 | } |
1909 | 941 | ||
1910 | static long cx25821_video_ioctl(struct file *file, | 942 | static const struct v4l2_ctrl_ops cx25821_ctrl_ops = { |
1911 | unsigned int cmd, unsigned long arg) | 943 | .s_ctrl = cx25821_s_ctrl, |
1912 | { | 944 | }; |
1913 | int ret = 0; | ||
1914 | |||
1915 | struct cx25821_fh *fh = file->private_data; | ||
1916 | |||
1917 | /* check to see if it's the video upstream */ | ||
1918 | if (fh->channel_id == SRAM_CH09) { | ||
1919 | ret = video_ioctl_upstream9(file, cmd, arg); | ||
1920 | return ret; | ||
1921 | } else if (fh->channel_id == SRAM_CH10) { | ||
1922 | ret = video_ioctl_upstream10(file, cmd, arg); | ||
1923 | return ret; | ||
1924 | } else if (fh->channel_id == SRAM_CH11) { | ||
1925 | ret = video_ioctl_upstream11(file, cmd, arg); | ||
1926 | ret = video_ioctl_set(file, cmd, arg); | ||
1927 | return ret; | ||
1928 | } | ||
1929 | |||
1930 | return video_ioctl2(file, cmd, arg); | ||
1931 | } | ||
1932 | 945 | ||
1933 | /* exported stuff */ | ||
1934 | static const struct v4l2_file_operations video_fops = { | 946 | static const struct v4l2_file_operations video_fops = { |
1935 | .owner = THIS_MODULE, | 947 | .owner = THIS_MODULE, |
1936 | .open = video_open, | 948 | .open = v4l2_fh_open, |
1937 | .release = video_release, | 949 | .release = video_release, |
1938 | .read = video_read, | 950 | .read = video_read, |
1939 | .poll = video_poll, | 951 | .poll = video_poll, |
1940 | .mmap = cx25821_video_mmap, | 952 | .mmap = cx25821_video_mmap, |
1941 | .ioctl = cx25821_video_ioctl, | 953 | .unlocked_ioctl = video_ioctl2, |
1942 | }; | 954 | }; |
1943 | 955 | ||
1944 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 956 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
@@ -1951,40 +963,170 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1951 | .vidioc_querybuf = cx25821_vidioc_querybuf, | 963 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
1952 | .vidioc_qbuf = cx25821_vidioc_qbuf, | 964 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
1953 | .vidioc_dqbuf = vidioc_dqbuf, | 965 | .vidioc_dqbuf = vidioc_dqbuf, |
1954 | #ifdef TUNER_FLAG | 966 | .vidioc_g_std = cx25821_vidioc_g_std, |
1955 | .vidioc_s_std = cx25821_vidioc_s_std, | 967 | .vidioc_s_std = cx25821_vidioc_s_std, |
1956 | .vidioc_querystd = cx25821_vidioc_querystd, | ||
1957 | #endif | ||
1958 | .vidioc_cropcap = cx25821_vidioc_cropcap, | ||
1959 | .vidioc_s_crop = cx25821_vidioc_s_crop, | ||
1960 | .vidioc_g_crop = cx25821_vidioc_g_crop, | ||
1961 | .vidioc_enum_input = cx25821_vidioc_enum_input, | 968 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
1962 | .vidioc_g_input = cx25821_vidioc_g_input, | 969 | .vidioc_g_input = cx25821_vidioc_g_input, |
1963 | .vidioc_s_input = cx25821_vidioc_s_input, | 970 | .vidioc_s_input = cx25821_vidioc_s_input, |
1964 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, | ||
1965 | .vidioc_s_ctrl = vidioc_s_ctrl, | ||
1966 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, | ||
1967 | .vidioc_streamon = vidioc_streamon, | 971 | .vidioc_streamon = vidioc_streamon, |
1968 | .vidioc_streamoff = vidioc_streamoff, | 972 | .vidioc_streamoff = vidioc_streamoff, |
1969 | .vidioc_log_status = vidioc_log_status, | 973 | .vidioc_log_status = vidioc_log_status, |
1970 | .vidioc_g_priority = cx25821_vidioc_g_priority, | 974 | .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, |
1971 | .vidioc_s_priority = cx25821_vidioc_s_priority, | 975 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
1972 | #ifdef TUNER_FLAG | ||
1973 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, | ||
1974 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, | ||
1975 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, | ||
1976 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, | ||
1977 | #endif | ||
1978 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1979 | .vidioc_g_register = cx25821_vidioc_g_register, | ||
1980 | .vidioc_s_register = cx25821_vidioc_s_register, | ||
1981 | #endif | ||
1982 | }; | 976 | }; |
1983 | 977 | ||
1984 | struct video_device cx25821_videoioctl_template = { | 978 | static const struct video_device cx25821_video_device = { |
1985 | .name = "cx25821-videoioctl", | 979 | .name = "cx25821-video", |
1986 | .fops = &video_fops, | 980 | .fops = &video_fops, |
981 | .release = video_device_release_empty, | ||
982 | .minor = -1, | ||
1987 | .ioctl_ops = &video_ioctl_ops, | 983 | .ioctl_ops = &video_ioctl_ops, |
1988 | .tvnorms = CX25821_NORMS, | 984 | .tvnorms = CX25821_NORMS, |
1989 | .current_norm = V4L2_STD_NTSC_M, | ||
1990 | }; | 985 | }; |
986 | |||
987 | static const struct v4l2_file_operations video_out_fops = { | ||
988 | .owner = THIS_MODULE, | ||
989 | .open = v4l2_fh_open, | ||
990 | .write = video_write, | ||
991 | .release = video_out_release, | ||
992 | .unlocked_ioctl = video_ioctl2, | ||
993 | }; | ||
994 | |||
995 | static const struct v4l2_ioctl_ops video_out_ioctl_ops = { | ||
996 | .vidioc_querycap = cx25821_vidioc_querycap, | ||
997 | .vidioc_enum_fmt_vid_out = cx25821_vidioc_enum_fmt_vid_cap, | ||
998 | .vidioc_g_fmt_vid_out = cx25821_vidioc_g_fmt_vid_cap, | ||
999 | .vidioc_try_fmt_vid_out = cx25821_vidioc_try_fmt_vid_out, | ||
1000 | .vidioc_s_fmt_vid_out = vidioc_s_fmt_vid_out, | ||
1001 | .vidioc_g_std = cx25821_vidioc_g_std, | ||
1002 | .vidioc_s_std = cx25821_vidioc_s_std, | ||
1003 | .vidioc_enum_output = cx25821_vidioc_enum_output, | ||
1004 | .vidioc_g_output = cx25821_vidioc_g_output, | ||
1005 | .vidioc_s_output = cx25821_vidioc_s_output, | ||
1006 | .vidioc_log_status = vidioc_log_status, | ||
1007 | }; | ||
1008 | |||
1009 | static const struct video_device cx25821_video_out_device = { | ||
1010 | .name = "cx25821-video", | ||
1011 | .fops = &video_out_fops, | ||
1012 | .release = video_device_release_empty, | ||
1013 | .minor = -1, | ||
1014 | .ioctl_ops = &video_out_ioctl_ops, | ||
1015 | .tvnorms = CX25821_NORMS, | ||
1016 | }; | ||
1017 | |||
1018 | void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) | ||
1019 | { | ||
1020 | cx_clear(PCI_INT_MSK, 1); | ||
1021 | |||
1022 | if (video_is_registered(&dev->channels[chan_num].vdev)) { | ||
1023 | video_unregister_device(&dev->channels[chan_num].vdev); | ||
1024 | v4l2_ctrl_handler_free(&dev->channels[chan_num].hdl); | ||
1025 | |||
1026 | btcx_riscmem_free(dev->pci, | ||
1027 | &dev->channels[chan_num].dma_vidq.stopper); | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | int cx25821_video_register(struct cx25821_dev *dev) | ||
1032 | { | ||
1033 | int err; | ||
1034 | int i; | ||
1035 | |||
1036 | /* initial device configuration */ | ||
1037 | dev->tvnorm = V4L2_STD_NTSC_M; | ||
1038 | |||
1039 | spin_lock_init(&dev->slock); | ||
1040 | |||
1041 | for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) { | ||
1042 | struct cx25821_channel *chan = &dev->channels[i]; | ||
1043 | struct video_device *vdev = &chan->vdev; | ||
1044 | struct v4l2_ctrl_handler *hdl = &chan->hdl; | ||
1045 | bool is_output = i > SRAM_CH08; | ||
1046 | |||
1047 | if (i == SRAM_CH08) /* audio channel */ | ||
1048 | continue; | ||
1049 | |||
1050 | if (!is_output) { | ||
1051 | v4l2_ctrl_handler_init(hdl, 4); | ||
1052 | v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops, | ||
1053 | V4L2_CID_BRIGHTNESS, 0, 10000, 1, 6200); | ||
1054 | v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops, | ||
1055 | V4L2_CID_CONTRAST, 0, 10000, 1, 5000); | ||
1056 | v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops, | ||
1057 | V4L2_CID_SATURATION, 0, 10000, 1, 5000); | ||
1058 | v4l2_ctrl_new_std(hdl, &cx25821_ctrl_ops, | ||
1059 | V4L2_CID_HUE, 0, 10000, 1, 5000); | ||
1060 | if (hdl->error) { | ||
1061 | err = hdl->error; | ||
1062 | goto fail_unreg; | ||
1063 | } | ||
1064 | err = v4l2_ctrl_handler_setup(hdl); | ||
1065 | if (err) | ||
1066 | goto fail_unreg; | ||
1067 | } else { | ||
1068 | chan->out = &dev->vid_out_data[i - SRAM_CH09]; | ||
1069 | chan->out->chan = chan; | ||
1070 | } | ||
1071 | |||
1072 | cx25821_risc_stopper(dev->pci, &chan->dma_vidq.stopper, | ||
1073 | chan->sram_channels->dma_ctl, 0x11, 0); | ||
1074 | |||
1075 | chan->sram_channels = &cx25821_sram_channels[i]; | ||
1076 | chan->width = 720; | ||
1077 | if (dev->tvnorm & V4L2_STD_625_50) | ||
1078 | chan->height = 576; | ||
1079 | else | ||
1080 | chan->height = 480; | ||
1081 | |||
1082 | if (chan->pixel_formats == PIXEL_FRMT_411) | ||
1083 | chan->fmt = cx25821_format_by_fourcc(V4L2_PIX_FMT_Y41P); | ||
1084 | else | ||
1085 | chan->fmt = cx25821_format_by_fourcc(V4L2_PIX_FMT_YUYV); | ||
1086 | |||
1087 | cx_write(chan->sram_channels->int_stat, 0xffffffff); | ||
1088 | |||
1089 | INIT_LIST_HEAD(&chan->dma_vidq.active); | ||
1090 | INIT_LIST_HEAD(&chan->dma_vidq.queued); | ||
1091 | |||
1092 | chan->timeout_data.dev = dev; | ||
1093 | chan->timeout_data.channel = &cx25821_sram_channels[i]; | ||
1094 | chan->dma_vidq.timeout.function = cx25821_vid_timeout; | ||
1095 | chan->dma_vidq.timeout.data = (unsigned long)&chan->timeout_data; | ||
1096 | init_timer(&chan->dma_vidq.timeout); | ||
1097 | |||
1098 | if (!is_output) | ||
1099 | videobuf_queue_sg_init(&chan->vidq, &cx25821_video_qops, &dev->pci->dev, | ||
1100 | &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1101 | V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), | ||
1102 | chan, &dev->lock); | ||
1103 | |||
1104 | /* register v4l devices */ | ||
1105 | *vdev = is_output ? cx25821_video_out_device : cx25821_video_device; | ||
1106 | vdev->v4l2_dev = &dev->v4l2_dev; | ||
1107 | if (!is_output) | ||
1108 | vdev->ctrl_handler = hdl; | ||
1109 | else | ||
1110 | vdev->vfl_dir = VFL_DIR_TX; | ||
1111 | vdev->lock = &dev->lock; | ||
1112 | set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags); | ||
1113 | snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i); | ||
1114 | video_set_drvdata(vdev, chan); | ||
1115 | |||
1116 | err = video_register_device(vdev, VFL_TYPE_GRABBER, | ||
1117 | video_nr[dev->nr]); | ||
1118 | |||
1119 | if (err < 0) | ||
1120 | goto fail_unreg; | ||
1121 | } | ||
1122 | |||
1123 | /* set PCI interrupt */ | ||
1124 | cx_set(PCI_INT_MSK, 0xff); | ||
1125 | |||
1126 | return 0; | ||
1127 | |||
1128 | fail_unreg: | ||
1129 | while (i >= 0) | ||
1130 | cx25821_video_unregister(dev, i--); | ||
1131 | return err; | ||
1132 | } | ||
diff --git a/drivers/media/pci/cx25821/cx25821-video.h b/drivers/media/pci/cx25821/cx25821-video.h index 11ba5eb93677..ab63b3858acf 100644 --- a/drivers/media/pci/cx25821/cx25821-video.h +++ b/drivers/media/pci/cx25821/cx25821-video.h | |||
@@ -39,8 +39,7 @@ | |||
39 | #include "cx25821.h" | 39 | #include "cx25821.h" |
40 | #include <media/v4l2-common.h> | 40 | #include <media/v4l2-common.h> |
41 | #include <media/v4l2-ioctl.h> | 41 | #include <media/v4l2-ioctl.h> |
42 | 42 | #include <media/v4l2-event.h> | |
43 | #define TUNER_FLAG | ||
44 | 43 | ||
45 | #define VIDEO_DEBUG 0 | 44 | #define VIDEO_DEBUG 0 |
46 | 45 | ||
@@ -50,137 +49,17 @@ do { \ | |||
50 | printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg); \ | 49 | printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg); \ |
51 | } while (0) | 50 | } while (0) |
52 | 51 | ||
53 | /* For IOCTL to identify running upstream */ | ||
54 | #define UPSTREAM_START_VIDEO 700 | ||
55 | #define UPSTREAM_STOP_VIDEO 701 | ||
56 | #define UPSTREAM_START_AUDIO 702 | ||
57 | #define UPSTREAM_STOP_AUDIO 703 | ||
58 | #define UPSTREAM_DUMP_REGISTERS 702 | ||
59 | #define SET_VIDEO_STD 800 | ||
60 | #define SET_PIXEL_FORMAT 1000 | ||
61 | #define ENABLE_CIF_RESOLUTION 1001 | ||
62 | |||
63 | #define REG_READ 900 | ||
64 | #define REG_WRITE 901 | ||
65 | #define MEDUSA_READ 910 | ||
66 | #define MEDUSA_WRITE 911 | ||
67 | |||
68 | extern struct sram_channel *channel0; | ||
69 | extern struct sram_channel *channel1; | ||
70 | extern struct sram_channel *channel2; | ||
71 | extern struct sram_channel *channel3; | ||
72 | extern struct sram_channel *channel4; | ||
73 | extern struct sram_channel *channel5; | ||
74 | extern struct sram_channel *channel6; | ||
75 | extern struct sram_channel *channel7; | ||
76 | extern struct sram_channel *channel9; | ||
77 | extern struct sram_channel *channel10; | ||
78 | extern struct sram_channel *channel11; | ||
79 | extern struct video_device cx25821_videoioctl_template; | ||
80 | /* extern const u32 *ctrl_classes[]; */ | ||
81 | |||
82 | extern unsigned int vid_limit; | ||
83 | |||
84 | #define FORMAT_FLAGS_PACKED 0x01 | 52 | #define FORMAT_FLAGS_PACKED 0x01 |
85 | extern struct cx25821_fmt formats[]; | ||
86 | extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc); | ||
87 | extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM]; | ||
88 | |||
89 | extern void cx25821_video_wakeup(struct cx25821_dev *dev, | 53 | extern void cx25821_video_wakeup(struct cx25821_dev *dev, |
90 | struct cx25821_dmaqueue *q, u32 count); | 54 | struct cx25821_dmaqueue *q, u32 count); |
91 | 55 | ||
92 | #ifdef TUNER_FLAG | ||
93 | extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm); | ||
94 | #endif | ||
95 | |||
96 | extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, | ||
97 | unsigned int bit); | ||
98 | extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit); | ||
99 | extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit); | ||
100 | extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, | ||
101 | unsigned int bits); | ||
102 | extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input); | ||
103 | extern int cx25821_start_video_dma(struct cx25821_dev *dev, | 56 | extern int cx25821_start_video_dma(struct cx25821_dev *dev, |
104 | struct cx25821_dmaqueue *q, | 57 | struct cx25821_dmaqueue *q, |
105 | struct cx25821_buffer *buf, | 58 | struct cx25821_buffer *buf, |
106 | struct sram_channel *channel); | 59 | const struct sram_channel *channel); |
107 | 60 | ||
108 | extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width, | ||
109 | unsigned int height, enum v4l2_field field); | ||
110 | extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); | 61 | extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status); |
111 | extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); | 62 | extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num); |
112 | extern int cx25821_video_register(struct cx25821_dev *dev); | 63 | extern int cx25821_video_register(struct cx25821_dev *dev); |
113 | extern int cx25821_get_format_size(void); | ||
114 | |||
115 | extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, | ||
116 | unsigned int *size); | ||
117 | extern int cx25821_buffer_prepare(struct videobuf_queue *q, | ||
118 | struct videobuf_buffer *vb, | ||
119 | enum v4l2_field field); | ||
120 | extern void cx25821_buffer_release(struct videobuf_queue *q, | ||
121 | struct videobuf_buffer *vb); | ||
122 | extern struct videobuf_queue *get_queue(struct cx25821_fh *fh); | ||
123 | extern int cx25821_get_resource(struct cx25821_fh *fh, int resource); | ||
124 | extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma); | ||
125 | extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | ||
126 | struct v4l2_format *f); | ||
127 | extern int cx25821_vidioc_querycap(struct file *file, void *priv, | ||
128 | struct v4l2_capability *cap); | ||
129 | extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | ||
130 | struct v4l2_fmtdesc *f); | ||
131 | extern int cx25821_vidioc_reqbufs(struct file *file, void *priv, | ||
132 | struct v4l2_requestbuffers *p); | ||
133 | extern int cx25821_vidioc_querybuf(struct file *file, void *priv, | ||
134 | struct v4l2_buffer *p); | ||
135 | extern int cx25821_vidioc_qbuf(struct file *file, void *priv, | ||
136 | struct v4l2_buffer *p); | ||
137 | extern int cx25821_vidioc_s_std(struct file *file, void *priv, | ||
138 | v4l2_std_id tvnorms); | ||
139 | extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i); | ||
140 | extern int cx25821_vidioc_enum_input(struct file *file, void *priv, | ||
141 | struct v4l2_input *i); | ||
142 | extern int cx25821_vidioc_g_input(struct file *file, void *priv, | ||
143 | unsigned int *i); | ||
144 | extern int cx25821_vidioc_s_input(struct file *file, void *priv, | ||
145 | unsigned int i); | ||
146 | extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv, | ||
147 | struct v4l2_control *ctl); | ||
148 | extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | ||
149 | struct v4l2_format *f); | ||
150 | extern int cx25821_vidioc_g_frequency(struct file *file, void *priv, | ||
151 | struct v4l2_frequency *f); | ||
152 | extern int cx25821_set_freq(struct cx25821_dev *dev, const struct v4l2_frequency *f); | ||
153 | extern int cx25821_vidioc_s_frequency(struct file *file, void *priv, | ||
154 | const struct v4l2_frequency *f); | ||
155 | extern int cx25821_vidioc_g_register(struct file *file, void *fh, | ||
156 | struct v4l2_dbg_register *reg); | ||
157 | extern int cx25821_vidioc_s_register(struct file *file, void *fh, | ||
158 | const struct v4l2_dbg_register *reg); | ||
159 | extern int cx25821_vidioc_g_tuner(struct file *file, void *priv, | ||
160 | struct v4l2_tuner *t); | ||
161 | extern int cx25821_vidioc_s_tuner(struct file *file, void *priv, | ||
162 | const struct v4l2_tuner *t); | ||
163 | |||
164 | extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm); | ||
165 | extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm); | ||
166 | |||
167 | extern int cx25821_vidioc_g_priority(struct file *file, void *f, | ||
168 | enum v4l2_priority *p); | ||
169 | extern int cx25821_vidioc_s_priority(struct file *file, void *f, | ||
170 | enum v4l2_priority prio); | ||
171 | |||
172 | extern int cx25821_vidioc_queryctrl(struct file *file, void *priv, | ||
173 | struct v4l2_queryctrl *qctrl); | ||
174 | extern int cx25821_set_control(struct cx25821_dev *dev, | ||
175 | struct v4l2_control *ctrl, int chan_num); | ||
176 | |||
177 | extern int cx25821_vidioc_cropcap(struct file *file, void *fh, | ||
178 | struct v4l2_cropcap *cropcap); | ||
179 | extern int cx25821_vidioc_s_crop(struct file *file, void *priv, | ||
180 | const struct v4l2_crop *crop); | ||
181 | extern int cx25821_vidioc_g_crop(struct file *file, void *priv, | ||
182 | struct v4l2_crop *crop); | ||
183 | 64 | ||
184 | extern int cx25821_vidioc_querystd(struct file *file, void *priv, | ||
185 | v4l2_std_id *norm); | ||
186 | #endif | 65 | #endif |
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h index 8a9c0c869412..90bdc196929f 100644 --- a/drivers/media/pci/cx25821/cx25821.h +++ b/drivers/media/pci/cx25821/cx25821.h | |||
@@ -33,17 +33,14 @@ | |||
33 | 33 | ||
34 | #include <media/v4l2-common.h> | 34 | #include <media/v4l2-common.h> |
35 | #include <media/v4l2-device.h> | 35 | #include <media/v4l2-device.h> |
36 | #include <media/tuner.h> | 36 | #include <media/v4l2-ctrls.h> |
37 | #include <media/tveeprom.h> | ||
38 | #include <media/videobuf-dma-sg.h> | 37 | #include <media/videobuf-dma-sg.h> |
39 | #include <media/videobuf-dvb.h> | ||
40 | 38 | ||
41 | #include "btcx-risc.h" | 39 | #include "btcx-risc.h" |
42 | #include "cx25821-reg.h" | 40 | #include "cx25821-reg.h" |
43 | #include "cx25821-medusa-reg.h" | 41 | #include "cx25821-medusa-reg.h" |
44 | #include "cx25821-sram.h" | 42 | #include "cx25821-sram.h" |
45 | #include "cx25821-audio.h" | 43 | #include "cx25821-audio.h" |
46 | #include "media/cx2341x.h" | ||
47 | 44 | ||
48 | #include <linux/version.h> | 45 | #include <linux/version.h> |
49 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
@@ -55,8 +52,6 @@ | |||
55 | 52 | ||
56 | #define CX25821_MAXBOARDS 2 | 53 | #define CX25821_MAXBOARDS 2 |
57 | 54 | ||
58 | #define TRUE 1 | ||
59 | #define FALSE 0 | ||
60 | #define LINE_SIZE_D1 1440 | 55 | #define LINE_SIZE_D1 1440 |
61 | 56 | ||
62 | /* Number of decoders and encoders */ | 57 | /* Number of decoders and encoders */ |
@@ -67,7 +62,6 @@ | |||
67 | 62 | ||
68 | /* Max number of inputs by card */ | 63 | /* Max number of inputs by card */ |
69 | #define MAX_CX25821_INPUT 8 | 64 | #define MAX_CX25821_INPUT 8 |
70 | #define INPUT(nr) (&cx25821_boards[dev->board].input[nr]) | ||
71 | #define RESOURCE_VIDEO0 1 | 65 | #define RESOURCE_VIDEO0 1 |
72 | #define RESOURCE_VIDEO1 2 | 66 | #define RESOURCE_VIDEO1 2 |
73 | #define RESOURCE_VIDEO2 4 | 67 | #define RESOURCE_VIDEO2 4 |
@@ -80,7 +74,6 @@ | |||
80 | #define RESOURCE_VIDEO9 512 | 74 | #define RESOURCE_VIDEO9 512 |
81 | #define RESOURCE_VIDEO10 1024 | 75 | #define RESOURCE_VIDEO10 1024 |
82 | #define RESOURCE_VIDEO11 2048 | 76 | #define RESOURCE_VIDEO11 2048 |
83 | #define RESOURCE_VIDEO_IOCTL 4096 | ||
84 | 77 | ||
85 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ | 78 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ |
86 | 79 | ||
@@ -97,7 +90,6 @@ | |||
97 | #define CX25821_BOARD_CONEXANT_ATHENA10 1 | 90 | #define CX25821_BOARD_CONEXANT_ATHENA10 1 |
98 | #define MAX_VID_CHANNEL_NUM 12 | 91 | #define MAX_VID_CHANNEL_NUM 12 |
99 | #define VID_CHANNEL_NUM 8 | 92 | #define VID_CHANNEL_NUM 8 |
100 | #define CX25821_NR_INPUT 2 | ||
101 | 93 | ||
102 | struct cx25821_fmt { | 94 | struct cx25821_fmt { |
103 | char *name; | 95 | char *name; |
@@ -107,14 +99,6 @@ struct cx25821_fmt { | |||
107 | u32 cxformat; | 99 | u32 cxformat; |
108 | }; | 100 | }; |
109 | 101 | ||
110 | struct cx25821_ctrl { | ||
111 | struct v4l2_queryctrl v; | ||
112 | u32 off; | ||
113 | u32 reg; | ||
114 | u32 mask; | ||
115 | u32 shift; | ||
116 | }; | ||
117 | |||
118 | struct cx25821_tvnorm { | 102 | struct cx25821_tvnorm { |
119 | char *name; | 103 | char *name; |
120 | v4l2_std_id id; | 104 | v4l2_std_id id; |
@@ -122,40 +106,6 @@ struct cx25821_tvnorm { | |||
122 | u32 cxoformat; | 106 | u32 cxoformat; |
123 | }; | 107 | }; |
124 | 108 | ||
125 | struct cx25821_fh { | ||
126 | struct cx25821_dev *dev; | ||
127 | enum v4l2_buf_type type; | ||
128 | int radio; | ||
129 | u32 resources; | ||
130 | |||
131 | enum v4l2_priority prio; | ||
132 | |||
133 | /* video overlay */ | ||
134 | struct v4l2_window win; | ||
135 | struct v4l2_clip *clips; | ||
136 | unsigned int nclips; | ||
137 | |||
138 | /* video capture */ | ||
139 | struct cx25821_fmt *fmt; | ||
140 | unsigned int width, height; | ||
141 | int channel_id; | ||
142 | |||
143 | /* vbi capture */ | ||
144 | struct videobuf_queue vidq; | ||
145 | struct videobuf_queue vbiq; | ||
146 | |||
147 | /* H264 Encoder specifics ONLY */ | ||
148 | struct videobuf_queue mpegq; | ||
149 | atomic_t v4l_reading; | ||
150 | }; | ||
151 | |||
152 | enum cx25821_itype { | ||
153 | CX25821_VMUX_COMPOSITE = 1, | ||
154 | CX25821_VMUX_SVIDEO, | ||
155 | CX25821_VMUX_DEBUG, | ||
156 | CX25821_RADIO, | ||
157 | }; | ||
158 | |||
159 | enum cx25821_src_sel_type { | 109 | enum cx25821_src_sel_type { |
160 | CX25821_SRC_SEL_EXT_656_VIDEO = 0, | 110 | CX25821_SRC_SEL_EXT_656_VIDEO = 0, |
161 | CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO | 111 | CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO |
@@ -169,16 +119,10 @@ struct cx25821_buffer { | |||
169 | /* cx25821 specific */ | 119 | /* cx25821 specific */ |
170 | unsigned int bpl; | 120 | unsigned int bpl; |
171 | struct btcx_riscmem risc; | 121 | struct btcx_riscmem risc; |
172 | struct cx25821_fmt *fmt; | 122 | const struct cx25821_fmt *fmt; |
173 | u32 count; | 123 | u32 count; |
174 | }; | 124 | }; |
175 | 125 | ||
176 | struct cx25821_input { | ||
177 | enum cx25821_itype type; | ||
178 | unsigned int vmux; | ||
179 | u32 gpio0, gpio1, gpio2, gpio3; | ||
180 | }; | ||
181 | |||
182 | enum port { | 126 | enum port { |
183 | CX25821_UNDEFINED = 0, | 127 | CX25821_UNDEFINED = 0, |
184 | CX25821_RAW, | 128 | CX25821_RAW, |
@@ -190,19 +134,8 @@ struct cx25821_board { | |||
190 | enum port porta; | 134 | enum port porta; |
191 | enum port portb; | 135 | enum port portb; |
192 | enum port portc; | 136 | enum port portc; |
193 | unsigned int tuner_type; | ||
194 | unsigned int radio_type; | ||
195 | unsigned char tuner_addr; | ||
196 | unsigned char radio_addr; | ||
197 | 137 | ||
198 | u32 clk_freq; | 138 | u32 clk_freq; |
199 | struct cx25821_input input[CX25821_NR_INPUT]; | ||
200 | }; | ||
201 | |||
202 | struct cx25821_subid { | ||
203 | u16 subvendor; | ||
204 | u16 subdevice; | ||
205 | u32 card; | ||
206 | }; | 139 | }; |
207 | 140 | ||
208 | struct cx25821_i2c { | 141 | struct cx25821_i2c { |
@@ -234,34 +167,70 @@ struct cx25821_dmaqueue { | |||
234 | 167 | ||
235 | struct cx25821_data { | 168 | struct cx25821_data { |
236 | struct cx25821_dev *dev; | 169 | struct cx25821_dev *dev; |
237 | struct sram_channel *channel; | 170 | const struct sram_channel *channel; |
171 | }; | ||
172 | |||
173 | struct cx25821_dev; | ||
174 | |||
175 | struct cx25821_channel; | ||
176 | |||
177 | struct cx25821_video_out_data { | ||
178 | struct cx25821_channel *chan; | ||
179 | int _line_size; | ||
180 | int _prog_cnt; | ||
181 | int _pixel_format; | ||
182 | int _is_first_frame; | ||
183 | int _is_running; | ||
184 | int _file_status; | ||
185 | int _lines_count; | ||
186 | int _frame_count; | ||
187 | unsigned int _risc_size; | ||
188 | |||
189 | __le32 *_dma_virt_start_addr; | ||
190 | __le32 *_dma_virt_addr; | ||
191 | dma_addr_t _dma_phys_addr; | ||
192 | dma_addr_t _dma_phys_start_addr; | ||
193 | |||
194 | unsigned int _data_buf_size; | ||
195 | __le32 *_data_buf_virt_addr; | ||
196 | dma_addr_t _data_buf_phys_addr; | ||
197 | |||
198 | u32 upstream_riscbuf_size; | ||
199 | u32 upstream_databuf_size; | ||
200 | int is_60hz; | ||
201 | int _frame_index; | ||
202 | int cur_frame_index; | ||
203 | int curpos; | ||
204 | wait_queue_head_t waitq; | ||
238 | }; | 205 | }; |
239 | 206 | ||
240 | struct cx25821_channel { | 207 | struct cx25821_channel { |
241 | struct v4l2_prio_state prio; | 208 | unsigned id; |
209 | struct cx25821_dev *dev; | ||
210 | struct v4l2_fh *streaming_fh; | ||
242 | 211 | ||
243 | int ctl_bright; | 212 | struct v4l2_ctrl_handler hdl; |
244 | int ctl_contrast; | ||
245 | int ctl_hue; | ||
246 | int ctl_saturation; | ||
247 | struct cx25821_data timeout_data; | 213 | struct cx25821_data timeout_data; |
248 | 214 | ||
249 | struct video_device *video_dev; | 215 | struct video_device vdev; |
250 | struct cx25821_dmaqueue vidq; | 216 | struct cx25821_dmaqueue dma_vidq; |
251 | 217 | struct videobuf_queue vidq; | |
252 | struct sram_channel *sram_channels; | ||
253 | 218 | ||
254 | struct mutex lock; | 219 | const struct sram_channel *sram_channels; |
255 | int resources; | ||
256 | 220 | ||
221 | const struct cx25821_fmt *fmt; | ||
222 | unsigned int width, height; | ||
257 | int pixel_formats; | 223 | int pixel_formats; |
258 | int use_cif_resolution; | 224 | int use_cif_resolution; |
259 | int cif_width; | 225 | int cif_width; |
226 | |||
227 | /* video output data for the video output channel */ | ||
228 | struct cx25821_video_out_data *out; | ||
260 | }; | 229 | }; |
261 | 230 | ||
231 | struct snd_card; | ||
232 | |||
262 | struct cx25821_dev { | 233 | struct cx25821_dev { |
263 | struct list_head devlist; | ||
264 | atomic_t refcount; | ||
265 | struct v4l2_device v4l2_dev; | 234 | struct v4l2_device v4l2_dev; |
266 | 235 | ||
267 | /* pci stuff */ | 236 | /* pci stuff */ |
@@ -273,6 +242,8 @@ struct cx25821_dev { | |||
273 | u8 __iomem *bmmio; | 242 | u8 __iomem *bmmio; |
274 | int pci_irqmask; | 243 | int pci_irqmask; |
275 | int hwrevision; | 244 | int hwrevision; |
245 | /* used by cx25821-alsa */ | ||
246 | struct snd_card *card; | ||
276 | 247 | ||
277 | u32 clk_freq; | 248 | u32 clk_freq; |
278 | 249 | ||
@@ -289,17 +260,8 @@ struct cx25821_dev { | |||
289 | char name[32]; | 260 | char name[32]; |
290 | 261 | ||
291 | /* Analog video */ | 262 | /* Analog video */ |
292 | u32 resources; | ||
293 | unsigned int input; | 263 | unsigned int input; |
294 | u32 tvaudio; | ||
295 | v4l2_std_id tvnorm; | 264 | v4l2_std_id tvnorm; |
296 | unsigned int tuner_type; | ||
297 | unsigned char tuner_addr; | ||
298 | unsigned int radio_type; | ||
299 | unsigned char radio_addr; | ||
300 | unsigned int has_radio; | ||
301 | unsigned int videc_type; | ||
302 | unsigned char videc_addr; | ||
303 | unsigned short _max_num_decoders; | 265 | unsigned short _max_num_decoders; |
304 | 266 | ||
305 | /* Analog Audio Upstream */ | 267 | /* Analog Audio Upstream */ |
@@ -323,132 +285,26 @@ struct cx25821_dev { | |||
323 | __le32 *_audiodata_buf_virt_addr; | 285 | __le32 *_audiodata_buf_virt_addr; |
324 | dma_addr_t _audiodata_buf_phys_addr; | 286 | dma_addr_t _audiodata_buf_phys_addr; |
325 | char *_audiofilename; | 287 | char *_audiofilename; |
326 | |||
327 | /* V4l */ | ||
328 | u32 freq; | ||
329 | struct video_device *vbi_dev; | ||
330 | struct video_device *radio_dev; | ||
331 | struct video_device *ioctl_dev; | ||
332 | |||
333 | spinlock_t slock; | ||
334 | |||
335 | /* Video Upstream */ | ||
336 | int _line_size; | ||
337 | int _prog_cnt; | ||
338 | int _pixel_format; | ||
339 | int _is_first_frame; | ||
340 | int _is_running; | ||
341 | int _file_status; | ||
342 | int _lines_count; | ||
343 | int _frame_count; | ||
344 | int _channel_upstream_select; | ||
345 | unsigned int _risc_size; | ||
346 | |||
347 | __le32 *_dma_virt_start_addr; | ||
348 | __le32 *_dma_virt_addr; | ||
349 | dma_addr_t _dma_phys_addr; | ||
350 | dma_addr_t _dma_phys_start_addr; | ||
351 | |||
352 | unsigned int _data_buf_size; | ||
353 | __le32 *_data_buf_virt_addr; | ||
354 | dma_addr_t _data_buf_phys_addr; | ||
355 | char *_filename; | ||
356 | char *_defaultname; | ||
357 | |||
358 | int _line_size_ch2; | ||
359 | int _prog_cnt_ch2; | ||
360 | int _pixel_format_ch2; | ||
361 | int _is_first_frame_ch2; | ||
362 | int _is_running_ch2; | ||
363 | int _file_status_ch2; | ||
364 | int _lines_count_ch2; | ||
365 | int _frame_count_ch2; | ||
366 | int _channel2_upstream_select; | ||
367 | unsigned int _risc_size_ch2; | ||
368 | |||
369 | __le32 *_dma_virt_start_addr_ch2; | ||
370 | __le32 *_dma_virt_addr_ch2; | ||
371 | dma_addr_t _dma_phys_addr_ch2; | ||
372 | dma_addr_t _dma_phys_start_addr_ch2; | ||
373 | |||
374 | unsigned int _data_buf_size_ch2; | ||
375 | __le32 *_data_buf_virt_addr_ch2; | ||
376 | dma_addr_t _data_buf_phys_addr_ch2; | ||
377 | char *_filename_ch2; | ||
378 | char *_defaultname_ch2; | ||
379 | |||
380 | /* MPEG Encoder ONLY settings */ | ||
381 | u32 cx23417_mailbox; | ||
382 | struct cx2341x_mpeg_params mpeg_params; | ||
383 | struct video_device *v4l_device; | ||
384 | atomic_t v4l_reader_count; | ||
385 | struct cx25821_tvnorm encodernorm; | ||
386 | |||
387 | u32 upstream_riscbuf_size; | ||
388 | u32 upstream_databuf_size; | ||
389 | u32 upstream_riscbuf_size_ch2; | ||
390 | u32 upstream_databuf_size_ch2; | ||
391 | u32 audio_upstream_riscbuf_size; | 288 | u32 audio_upstream_riscbuf_size; |
392 | u32 audio_upstream_databuf_size; | 289 | u32 audio_upstream_databuf_size; |
393 | int _isNTSC; | ||
394 | int _frame_index; | ||
395 | int _audioframe_index; | 290 | int _audioframe_index; |
396 | struct workqueue_struct *_irq_queues; | ||
397 | struct work_struct _irq_work_entry; | ||
398 | struct workqueue_struct *_irq_queues_ch2; | ||
399 | struct work_struct _irq_work_entry_ch2; | ||
400 | struct workqueue_struct *_irq_audio_queues; | 291 | struct workqueue_struct *_irq_audio_queues; |
401 | struct work_struct _audio_work_entry; | 292 | struct work_struct _audio_work_entry; |
402 | char *input_filename; | ||
403 | char *input_filename_ch2; | ||
404 | int _frame_index_ch2; | ||
405 | int _isNTSC_ch2; | ||
406 | char *vid_stdname_ch2; | ||
407 | int pixel_format_ch2; | ||
408 | int channel_select_ch2; | ||
409 | int command_ch2; | ||
410 | char *input_audiofilename; | 293 | char *input_audiofilename; |
411 | char *vid_stdname; | ||
412 | int pixel_format; | ||
413 | int channel_select; | ||
414 | int command; | ||
415 | int channel_opened; | ||
416 | }; | ||
417 | 294 | ||
418 | struct upstream_user_struct { | 295 | /* V4l */ |
419 | char *input_filename; | 296 | spinlock_t slock; |
420 | char *vid_stdname; | ||
421 | int pixel_format; | ||
422 | int channel_select; | ||
423 | int command; | ||
424 | }; | ||
425 | 297 | ||
426 | struct downstream_user_struct { | 298 | /* Video Upstream */ |
427 | char *vid_stdname; | 299 | struct cx25821_video_out_data vid_out_data[2]; |
428 | int pixel_format; | ||
429 | int cif_resolution_enable; | ||
430 | int cif_width; | ||
431 | int decoder_select; | ||
432 | int command; | ||
433 | int reg_address; | ||
434 | int reg_data; | ||
435 | }; | 300 | }; |
436 | 301 | ||
437 | extern struct upstream_user_struct *up_data; | ||
438 | |||
439 | static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) | 302 | static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) |
440 | { | 303 | { |
441 | return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); | 304 | return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev); |
442 | } | 305 | } |
443 | 306 | ||
444 | #define cx25821_call_all(dev, o, f, args...) \ | ||
445 | v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) | ||
446 | |||
447 | extern struct list_head cx25821_devlist; | ||
448 | extern struct mutex cx25821_devlist_mutex; | ||
449 | |||
450 | extern struct cx25821_board cx25821_boards[]; | 307 | extern struct cx25821_board cx25821_boards[]; |
451 | extern struct cx25821_subid cx25821_subids[]; | ||
452 | 308 | ||
453 | #define SRAM_CH00 0 /* Video A */ | 309 | #define SRAM_CH00 0 /* Video A */ |
454 | #define SRAM_CH01 1 /* Video B */ | 310 | #define SRAM_CH01 1 /* Video B */ |
@@ -467,7 +323,6 @@ extern struct cx25821_subid cx25821_subids[]; | |||
467 | #define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09 | 323 | #define VID_UPSTREAM_SRAM_CHANNEL_I SRAM_CH09 |
468 | #define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10 | 324 | #define VID_UPSTREAM_SRAM_CHANNEL_J SRAM_CH10 |
469 | #define AUDIO_UPSTREAM_SRAM_CHANNEL_B SRAM_CH11 | 325 | #define AUDIO_UPSTREAM_SRAM_CHANNEL_B SRAM_CH11 |
470 | #define VIDEO_IOCTL_CH 11 | ||
471 | 326 | ||
472 | struct sram_channel { | 327 | struct sram_channel { |
473 | char *name; | 328 | char *name; |
@@ -503,10 +358,8 @@ struct sram_channel { | |||
503 | u32 jumponly; | 358 | u32 jumponly; |
504 | u32 irq_bit; | 359 | u32 irq_bit; |
505 | }; | 360 | }; |
506 | extern struct sram_channel cx25821_sram_channels[]; | ||
507 | 361 | ||
508 | #define STATUS_SUCCESS 0 | 362 | extern const struct sram_channel cx25821_sram_channels[]; |
509 | #define STATUS_UNSUCCESSFUL -1 | ||
510 | 363 | ||
511 | #define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) | 364 | #define cx_read(reg) readl(dev->lmmio + ((reg)>>2)) |
512 | #define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2)) | 365 | #define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2)) |
@@ -529,8 +382,6 @@ extern struct sram_channel cx25821_sram_channels[]; | |||
529 | pr_info("(%d): " fmt, dev->board, ##args) | 382 | pr_info("(%d): " fmt, dev->board, ##args) |
530 | 383 | ||
531 | extern int cx25821_i2c_register(struct cx25821_i2c *bus); | 384 | extern int cx25821_i2c_register(struct cx25821_i2c *bus); |
532 | extern void cx25821_card_setup(struct cx25821_dev *dev); | ||
533 | extern int cx25821_ir_init(struct cx25821_dev *dev); | ||
534 | extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); | 385 | extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value); |
535 | extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); | 386 | extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value); |
536 | extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); | 387 | extern int cx25821_i2c_unregister(struct cx25821_i2c *bus); |
@@ -551,7 +402,7 @@ extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation, | |||
551 | int decoder); | 402 | int decoder); |
552 | 403 | ||
553 | extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, | 404 | extern int cx25821_sram_channel_setup(struct cx25821_dev *dev, |
554 | struct sram_channel *ch, unsigned int bpl, | 405 | const struct sram_channel *ch, unsigned int bpl, |
555 | u32 risc); | 406 | u32 risc); |
556 | 407 | ||
557 | extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | 408 | extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, |
@@ -570,46 +421,31 @@ extern void cx25821_free_buffer(struct videobuf_queue *q, | |||
570 | extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, | 421 | extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc, |
571 | u32 reg, u32 mask, u32 value); | 422 | u32 reg, u32 mask, u32 value); |
572 | extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, | 423 | extern void cx25821_sram_channel_dump(struct cx25821_dev *dev, |
573 | struct sram_channel *ch); | 424 | const struct sram_channel *ch); |
574 | extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, | 425 | extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev, |
575 | struct sram_channel *ch); | 426 | const struct sram_channel *ch); |
576 | 427 | ||
577 | extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci); | 428 | extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci); |
578 | extern void cx25821_print_irqbits(char *name, char *tag, char **strings, | 429 | extern void cx25821_print_irqbits(char *name, char *tag, char **strings, |
579 | int len, u32 bits, u32 mask); | 430 | int len, u32 bits, u32 mask); |
580 | extern void cx25821_dev_unregister(struct cx25821_dev *dev); | 431 | extern void cx25821_dev_unregister(struct cx25821_dev *dev); |
581 | extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, | 432 | extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev, |
582 | struct sram_channel *ch, | 433 | const struct sram_channel *ch, |
583 | unsigned int bpl, u32 risc); | 434 | unsigned int bpl, u32 risc); |
584 | 435 | ||
585 | extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, | 436 | extern int cx25821_vidupstream_init(struct cx25821_channel *chan, int pixel_format); |
586 | int channel_select, int pixel_format); | ||
587 | extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, | ||
588 | int channel_select, int pixel_format); | ||
589 | extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, | 437 | extern int cx25821_audio_upstream_init(struct cx25821_dev *dev, |
590 | int channel_select); | 438 | int channel_select); |
591 | extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev); | 439 | extern int cx25821_write_frame(struct cx25821_channel *chan, |
592 | extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev); | 440 | const char __user *data, size_t count); |
441 | extern void cx25821_free_mem_upstream(struct cx25821_channel *chan); | ||
593 | extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); | 442 | extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev); |
594 | extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev, | 443 | extern void cx25821_stop_upstream_video(struct cx25821_channel *chan); |
595 | struct upstream_user_struct | ||
596 | *up_data); | ||
597 | extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev, | ||
598 | struct upstream_user_struct | ||
599 | *up_data); | ||
600 | extern void cx25821_start_upstream_audio(struct cx25821_dev *dev, | ||
601 | struct upstream_user_struct *up_data); | ||
602 | extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev); | ||
603 | extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev); | ||
604 | extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); | 444 | extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev); |
605 | extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, | 445 | extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, |
606 | struct sram_channel *ch, | 446 | const struct sram_channel *ch, |
607 | unsigned int bpl, u32 risc); | 447 | unsigned int bpl, u32 risc); |
608 | extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, | 448 | extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel, |
609 | u32 format); | 449 | u32 format); |
610 | extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev); | 450 | |
611 | extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | ||
612 | struct pci_dev *pci, | ||
613 | struct video_device *template, | ||
614 | char *type); | ||
615 | #endif | 451 | #endif |