diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-14 19:13:30 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 23:36:22 +0400 |
commit | b285192a43f0432d82c2c10974204e78af0da596 (patch) | |
tree | 618aa87e760c9c949eca9e4df6ae0eeffa11dcfc /drivers/media/video/ivtv | |
parent | 68de959f773a1d49096835c411390bceff5d1549 (diff) | |
download | linux-b285192a43f0432d82c2c10974204e78af0da596.tar.xz |
[media] rename most media/video pci drivers to media/pci
Rename all PCI drivers with their own directory under
drivers/media/video into drivers/media/pci and update the
building system.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/ivtv')
36 files changed, 0 insertions, 15593 deletions
diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig deleted file mode 100644 index 89f65914cc8e..000000000000 --- a/drivers/media/video/ivtv/Kconfig +++ /dev/null @@ -1,45 +0,0 @@ -config VIDEO_IVTV - tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" - depends on VIDEO_V4L2 && PCI && I2C - select I2C_ALGOBIT - depends on RC_CORE - select VIDEO_TUNER - select VIDEO_TVEEPROM - select VIDEO_CX2341X - select VIDEO_CX25840 - select VIDEO_MSP3400 - select VIDEO_SAA711X - select VIDEO_SAA717X - select VIDEO_SAA7127 - select VIDEO_CS53L32A - select VIDEO_M52790 - select VIDEO_WM8775 - select VIDEO_WM8739 - select VIDEO_VP27SMPX - select VIDEO_UPD64031A - select VIDEO_UPD64083 - ---help--- - This is a video4linux driver for Conexant cx23416 or cx23415 based - PCI personal video recorder devices. - - This is used in devices such as the Hauppauge PVR-150/250/350/500 - cards. There is a driver homepage at <http://www.ivtvdriver.org>. - - To compile this driver as a module, choose M here: the - module will be called ivtv. - -config VIDEO_FB_IVTV - tristate "Conexant cx23415 framebuffer support" - depends on VIDEO_IVTV && FB - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - This is a framebuffer driver for the Conexant cx23415 MPEG - encoder/decoder. - - This is used in the Hauppauge PVR-350 card. There is a driver - homepage at <http://www.ivtvdriver.org>. - - To compile this driver as a module, choose M here: the - module will be called ivtvfb. diff --git a/drivers/media/video/ivtv/Makefile b/drivers/media/video/ivtv/Makefile deleted file mode 100644 index 80b4ec18475d..000000000000 --- a/drivers/media/video/ivtv/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -ivtv-objs := ivtv-routing.o ivtv-cards.o ivtv-controls.o \ - ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \ - ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \ - ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \ - ivtv-vbi.o ivtv-yuv.o - -obj-$(CONFIG_VIDEO_IVTV) += ivtv.o -obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o - -ccflags-y += -I$(srctree)/drivers/media/video -ccflags-y += -I$(srctree)/drivers/media/tuners -ccflags-y += -I$(srctree)/drivers/media/dvb-core -ccflags-y += -I$(srctree)/drivers/media/dvb-frontends - diff --git a/drivers/media/video/ivtv/ivtv-cards.c b/drivers/media/video/ivtv/ivtv-cards.c deleted file mode 100644 index 145e4749a69d..000000000000 --- a/drivers/media/video/ivtv/ivtv-cards.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - Functions to query card hardware - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-cards.h" -#include "ivtv-i2c.h" - -#include <media/msp3400.h> -#include <media/m52790.h> -#include <media/wm8775.h> -#include <media/cs53l32a.h> -#include <media/cx25840.h> -#include <media/upd64031a.h> - -#define MSP_TUNER MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \ - MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER) -#define MSP_SCART1 MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \ - MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) -#define MSP_SCART2 MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, \ - MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) -#define MSP_SCART3 MSP_INPUT(MSP_IN_SCART3, MSP_IN_TUNER1, \ - MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) -#define MSP_MONO MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \ - MSP_DSP_IN_SCART, MSP_DSP_IN_SCART) - -#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM) - -/* usual i2c tuner addresses to probe */ -static struct ivtv_card_tuner_i2c ivtv_i2c_std = { - .radio = { I2C_CLIENT_END }, - .demod = { 0x43, I2C_CLIENT_END }, - .tv = { 0x61, 0x60, I2C_CLIENT_END }, -}; - -/* as above, but with possible radio tuner */ -static struct ivtv_card_tuner_i2c ivtv_i2c_radio = { - .radio = { 0x60, I2C_CLIENT_END }, - .demod = { 0x43, I2C_CLIENT_END }, - .tv = { 0x61, I2C_CLIENT_END }, -}; - -/* using the tda8290+75a combo */ -static struct ivtv_card_tuner_i2c ivtv_i2c_tda8290 = { - .radio = { I2C_CLIENT_END }, - .demod = { I2C_CLIENT_END }, - .tv = { 0x4b, I2C_CLIENT_END }, -}; - -/********************** card configuration *******************************/ - -/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ - This keeps the PCI ID database up to date. Note that the entries - must be added under vendor 0x4444 (Conexant) as subsystem IDs. - New vendor IDs should still be added to the vendor ID list. */ - -/* Hauppauge PVR-250 cards */ - -/* Note: for Hauppauge cards the tveeprom information is used instead of PCI IDs */ -static const struct ivtv_card ivtv_card_pvr250 = { - .type = IVTV_CARD_PVR_250, - .name = "Hauppauge WinTV PVR-250", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_MSP34XX, - .hw_audio_ctrl = IVTV_HW_MSP34XX, - .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | - IVTV_HW_TVEEPROM | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, - { IVTV_CARD_INPUT_SVIDEO2, 2, IVTV_SAA71XX_SVIDEO1 }, - { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 }, - { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, MSP_SCART1 }, - { IVTV_CARD_INPUT_LINE_IN2, MSP_SCART3 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 }, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Hauppauge PVR-350 cards */ - -/* Outputs for Hauppauge PVR350 cards */ -static struct ivtv_card_output ivtv_pvr350_outputs[] = { - { - .name = "S-Video + Composite", - .video_output = 0, - }, { - .name = "Composite", - .video_output = 1, - }, { - .name = "S-Video", - .video_output = 2, - }, { - .name = "RGB", - .video_output = 3, - }, { - .name = "YUV C", - .video_output = 4, - }, { - .name = "YUV V", - .video_output = 5, - } -}; - -static const struct ivtv_card ivtv_card_pvr350 = { - .type = IVTV_CARD_PVR_350, - .name = "Hauppauge WinTV PVR-350", - .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER, - .video_outputs = ivtv_pvr350_outputs, - .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs), - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_MSP34XX, - .hw_audio_ctrl = IVTV_HW_MSP34XX, - .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | - IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER | - IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, - { IVTV_CARD_INPUT_SVIDEO2, 2, IVTV_SAA71XX_SVIDEO1 }, - { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 }, - { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, MSP_SCART1 }, - { IVTV_CARD_INPUT_LINE_IN2, MSP_SCART3 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 }, - .i2c = &ivtv_i2c_std, -}; - -/* PVR-350 V1 boards have a different audio tuner input and use a - saa7114 instead of a saa7115. - Note that the info below comes from a pre-production model so it may - not be correct. Especially the audio behaves strangely (mono only it seems) */ -static const struct ivtv_card ivtv_card_pvr350_v1 = { - .type = IVTV_CARD_PVR_350_V1, - .name = "Hauppauge WinTV PVR-350 (V1)", - .v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER, - .video_outputs = ivtv_pvr350_outputs, - .nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs), - .hw_video = IVTV_HW_SAA7114, - .hw_audio = IVTV_HW_MSP34XX, - .hw_audio_ctrl = IVTV_HW_MSP34XX, - .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7114 | - IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, - { IVTV_CARD_INPUT_SVIDEO2, 2, IVTV_SAA71XX_SVIDEO1 }, - { IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 }, - { IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, MSP_MONO }, - { IVTV_CARD_INPUT_LINE_IN1, MSP_SCART1 }, - { IVTV_CARD_INPUT_LINE_IN2, MSP_SCART3 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 }, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Hauppauge PVR-150/PVR-500 cards */ - -static const struct ivtv_card ivtv_card_pvr150 = { - .type = IVTV_CARD_PVR_150, - .name = "Hauppauge WinTV PVR-150", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_muxer = IVTV_HW_WM8775, - .hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 | - IVTV_HW_TVEEPROM | IVTV_HW_TUNER | - IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT | - IVTV_HW_Z8F0811_IR_HAUP, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE7 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO1 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 }, - { IVTV_CARD_INPUT_SVIDEO2, 2, CX25840_SVIDEO2 }, - { IVTV_CARD_INPUT_COMPOSITE2, 2, CX25840_COMPOSITE4 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, - CX25840_AUDIO8, WM8775_AIN2 }, - { IVTV_CARD_INPUT_LINE_IN1, - CX25840_AUDIO_SERIAL, WM8775_AIN2 }, - { IVTV_CARD_INPUT_LINE_IN2, - CX25840_AUDIO_SERIAL, WM8775_AIN3 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, - CX25840_AUDIO_SERIAL, WM8775_AIN4 }, - /* apparently needed for the IR blaster */ - .gpio_init = { .direction = 0x1f01, .initial_value = 0x26f3 }, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* AVerMedia M179 cards */ - -static const struct ivtv_card_pci_info ivtv_pci_m179[] = { - { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3cf }, - { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3ce }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_m179 = { - .type = IVTV_CARD_M179, - .name = "AVerMedia M179", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7114, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_GPIO, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0xe380, .initial_value = 0x8290 }, - .gpio_audio_input = { .mask = 0x8040, .tuner = 0x8000, .linein = 0x0000 }, - .gpio_audio_mute = { .mask = 0x2000, .mute = 0x2000 }, - .gpio_audio_mode = { .mask = 0x4300, .mono = 0x4000, .stereo = 0x0200, - .lang1 = 0x0200, .lang2 = 0x0100, .both = 0x0000 }, - .gpio_audio_freq = { .mask = 0x0018, .f32000 = 0x0000, - .f44100 = 0x0008, .f48000 = 0x0010 }, - .gpio_audio_detect = { .mask = 0x4000, .stereo = 0x0000 }, - .tuners = { - /* As far as we know all M179 cards use this tuner */ - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_NTSC }, - }, - .pci_list = ivtv_pci_m179, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Yuan MPG600/Kuroutoshikou ITVC16-STVLP cards */ - -static const struct ivtv_card_pci_info ivtv_pci_mpg600[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xfff3 }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xffff }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_mpg600 = { - .type = IVTV_CARD_MPG600, - .name = "Yuan MPG600, Kuroutoshikou ITVC16-STVLP", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_GPIO, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0x3080, .initial_value = 0x0004 }, - .gpio_audio_input = { .mask = 0x3000, .tuner = 0x0000, .linein = 0x2000 }, - .gpio_audio_mute = { .mask = 0x0001, .mute = 0x0001 }, - .gpio_audio_mode = { .mask = 0x000e, .mono = 0x0006, .stereo = 0x0004, - .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 }, - .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 }, - .tuners = { - /* The PAL tuner is confirmed */ - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME }, - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_mpg600, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Yuan MPG160/Kuroutoshikou ITVC15-STVLP cards */ - -static const struct ivtv_card_pci_info ivtv_pci_mpg160[] = { - { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_YUAN1, 0 }, - { PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_IODATA, 0x40a0 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_mpg160 = { - .type = IVTV_CARD_MPG160, - .name = "YUAN MPG160, Kuroutoshikou ITVC15-STVLP, I/O Data GV-M2TV/PCI", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7114, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_GPIO, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0x7080, .initial_value = 0x400c }, - .gpio_audio_input = { .mask = 0x3000, .tuner = 0x0000, .linein = 0x2000 }, - .gpio_audio_mute = { .mask = 0x0001, .mute = 0x0001 }, - .gpio_audio_mode = { .mask = 0x000e, .mono = 0x0006, .stereo = 0x0004, - .lang1 = 0x0004, .lang2 = 0x0000, .both = 0x0008 }, - .gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 }, - .tuners = { - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME }, - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_mpg160, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Yuan PG600/Diamond PVR-550 cards */ - -static const struct ivtv_card_pci_info ivtv_pci_pg600[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_DIAMONDMM, 0x0070 }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_pg600 = { - .type = IVTV_CARD_PG600, - .name = "Yuan PG600, Diamond PVR-550", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, - }, - .tuners = { - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME }, - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_pg600, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Adaptec VideOh! AVC-2410 card */ - -static const struct ivtv_card_pci_info ivtv_pci_avc2410[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0093 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_avc2410 = { - .type = IVTV_CARD_AVC2410, - .name = "Adaptec VideOh! AVC-2410", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_MSP34XX, - .hw_audio_ctrl = IVTV_HW_MSP34XX, - .hw_muxer = IVTV_HW_CS53L32A, - .hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A | - IVTV_HW_SAA7115 | IVTV_HW_TUNER | - IVTV_HW_I2C_IR_RX_ADAPTEC, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, - MSP_TUNER, CS53L32A_IN0 }, - { IVTV_CARD_INPUT_LINE_IN1, - MSP_SCART1, CS53L32A_IN2 }, - }, - /* This card has no eeprom and in fact the Windows driver relies - on the country/region setting of the user to decide which tuner - is available. */ - .tuners = { - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - { .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP, - .tuner = TUNER_PHILIPS_FM1236_MK3 }, - { .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_avc2410, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Adaptec VideOh! AVC-2010 card */ - -static const struct ivtv_card_pci_info ivtv_pci_avc2010[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0092 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_avc2010 = { - .type = IVTV_CARD_AVC2010, - .name = "Adaptec VideOh! AVC-2010", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_CS53L32A, - .hw_audio_ctrl = IVTV_HW_CS53L32A, - .hw_all = IVTV_HW_CS53L32A | IVTV_HW_SAA7115, - .video_inputs = { - { IVTV_CARD_INPUT_SVIDEO1, 0, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 0, IVTV_SAA71XX_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_LINE_IN1, CS53L32A_IN2 }, - }, - /* Does not have a tuner */ - .pci_list = ivtv_pci_avc2010, -}; - -/* ------------------------------------------------------------------------- */ - -/* Nagase Transgear 5000TV card */ - -static const struct ivtv_card_pci_info ivtv_pci_tg5000tv[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_tg5000tv = { - .type = IVTV_CARD_TG5000TV, - .name = "Nagase Transgear 5000TV", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7114 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X | - IVTV_HW_GPIO, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_GPIO, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER | - IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO2 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gr_config = UPD64031A_VERTICAL_EXTERNAL, - .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 }, - .gpio_audio_input = { .mask = 0x8080, .tuner = 0x8000, .linein = 0x0080 }, - .gpio_audio_mute = { .mask = 0x6000, .mute = 0x6000 }, - .gpio_audio_mode = { .mask = 0x4300, .mono = 0x4000, .stereo = 0x0200, - .lang1 = 0x0300, .lang2 = 0x0000, .both = 0x0200 }, - .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000, - .composite = 0x0010, .svideo = 0x0020 }, - .tuners = { - { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_tg5000tv, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* AOpen VA2000MAX-SNT6 card */ - -static const struct ivtv_card_pci_info ivtv_pci_va2000[] = { - { PCI_DEVICE_ID_IVTV16, 0, 0xff5f }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_va2000 = { - .type = IVTV_CARD_VA2000MAX_SNT6, - .name = "AOpen VA2000MAX-SNT6", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD6408X, - .hw_audio = IVTV_HW_MSP34XX, - .hw_audio_ctrl = IVTV_HW_MSP34XX, - .hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 | - IVTV_HW_UPD6408X | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER }, - }, - .tuners = { - { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_va2000, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Yuan MPG600GR/Kuroutoshikou CX23416GYC-STVLP cards */ - -static const struct ivtv_card_pci_info ivtv_pci_cx23416gyc[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN4, 0x0600 }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x0523 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_cx23416gyc = { - .type = IVTV_CARD_CX23416GYC, - .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | - IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, - .hw_audio = IVTV_HW_SAA717X, - .hw_audio_ctrl = IVTV_HW_SAA717X, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER | - IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO3 | - IVTV_SAA717X_TUNER_FLAG }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN2 }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN0 }, - }, - .gr_config = UPD64031A_VERTICAL_EXTERNAL, - .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 }, - .gpio_video_input = { .mask = 0x0020, .tuner = 0x0000, - .composite = 0x0020, .svideo = 0x0020 }, - .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, - .f44100 = 0x4000, .f48000 = 0x8000 }, - .tuners = { - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, - }, - .pci_list = ivtv_pci_cx23416gyc, - .i2c = &ivtv_i2c_std, -}; - -static const struct ivtv_card ivtv_card_cx23416gyc_nogr = { - .type = IVTV_CARD_CX23416GYC_NOGR, - .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR)", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | IVTV_HW_UPD6408X, - .hw_audio = IVTV_HW_SAA717X, - .hw_audio_ctrl = IVTV_HW_SAA717X, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER | - IVTV_HW_UPD6408X, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 | - IVTV_SAA717X_TUNER_FLAG }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN2 }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN0 }, - }, - .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 }, - .gpio_video_input = { .mask = 0x0020, .tuner = 0x0000, - .composite = 0x0020, .svideo = 0x0020 }, - .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, - .f44100 = 0x4000, .f48000 = 0x8000 }, - .tuners = { - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, - }, - .i2c = &ivtv_i2c_std, -}; - -static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = { - .type = IVTV_CARD_CX23416GYC_NOGRYCS, - .name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR/YCS)", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO, - .hw_audio = IVTV_HW_SAA717X, - .hw_audio_ctrl = IVTV_HW_SAA717X, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 | - IVTV_SAA717X_TUNER_FLAG }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN2 }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN0 }, - }, - .gpio_init = { .direction = 0xf880, .initial_value = 0x8800 }, - .gpio_video_input = { .mask = 0x0020, .tuner = 0x0000, - .composite = 0x0020, .svideo = 0x0020 }, - .gpio_audio_freq = { .mask = 0xc000, .f32000 = 0x0000, - .f44100 = 0x4000, .f48000 = 0x8000 }, - .tuners = { - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 }, - }, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* I/O Data GV-MVP/RX & GV-MVP/RX2W (dual tuner) cards */ - -static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd01e }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd038 }, /* 2W unit #1 */ - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd039 }, /* 2W unit #2 */ - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_gv_mvprx = { - .type = IVTV_CARD_GV_MVPRX, - .name = "I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_WM8739, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_VP27SMPX | - IVTV_HW_TUNER | IVTV_HW_WM8739 | - IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO1 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 }, - .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 }, - .tuners = { - /* This card has the Panasonic VP27 tuner */ - { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 }, - }, - .pci_list = ivtv_pci_gv_mvprx, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* I/O Data GV-MVP/RX2E card */ - -static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx2e[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd025 }, - {0, 0, 0} -}; - -static const struct ivtv_card ivtv_card_gv_mvprx2e = { - .type = IVTV_CARD_GV_MVPRX2E, - .name = "I/O Data GV-MVP/RX2E", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_WM8739, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER | - IVTV_HW_VP27SMPX | IVTV_HW_WM8739, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE4 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0xc301, .initial_value = 0x0200 }, - .gpio_audio_input = { .mask = 0xffff, .tuner = 0x0200, .linein = 0x0300 }, - .tuners = { - /* This card has the Panasonic VP27 tuner */ - { .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 }, - }, - .pci_list = ivtv_pci_gv_mvprx2e, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* GotVIEW PCI DVD card */ - -static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_gotview_pci_dvd = { - .type = IVTV_CARD_GOTVIEW_PCI_DVD, - .name = "GotView PCI DVD", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA717X, - .hw_audio = IVTV_HW_SAA717X, - .hw_audio_ctrl = IVTV_HW_SAA717X, - .hw_all = IVTV_HW_SAA717X | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE1 }, /* pin 116 */ - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO0 }, /* pin 114/109 */ - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 }, /* pin 118 */ - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_SAA717X_IN0 }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_SAA717X_IN2 }, - }, - .gpio_init = { .direction = 0xf000, .initial_value = 0xA000 }, - .tuners = { - /* This card has a Philips FQ1216ME MK3 tuner */ - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - }, - .pci_list = ivtv_pci_gotview_pci_dvd, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* GotVIEW PCI DVD2 Deluxe card */ - -static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd2[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW1, 0x0600 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = { - .type = IVTV_CARD_GOTVIEW_PCI_DVD2, - .name = "GotView PCI DVD2 Deluxe", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_muxer = IVTV_HW_GPIO, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, 0 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, - .gpio_init = { .direction = 0x0800, .initial_value = 0 }, - .gpio_audio_input = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 }, - .tuners = { - /* This card has a Philips FQ1216ME MK5 tuner */ - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 }, - }, - .pci_list = ivtv_pci_gotview_pci_dvd2, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Yuan MPC622 miniPCI card */ - -static const struct ivtv_card_pci_info ivtv_pci_yuan_mpc622[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN2, 0xd998 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_yuan_mpc622 = { - .type = IVTV_CARD_YUAN_MPC622, - .name = "Yuan MPC622", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, - }, - .gpio_init = { .direction = 0x00ff, .initial_value = 0x0002 }, - .tuners = { - /* This card has the TDA8290/TDA8275 tuner chips */ - { .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_TDA8290 }, - }, - .pci_list = ivtv_pci_yuan_mpc622, - .i2c = &ivtv_i2c_tda8290, -}; - -/* ------------------------------------------------------------------------- */ - -/* DIGITAL COWBOY DCT-MTVP1 card */ - -static const struct ivtv_card_pci_info ivtv_pci_dctmvtvp1[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_dctmvtvp1 = { - .type = IVTV_CARD_DCTMTVP1, - .name = "Digital Cowboy DCT-MTVP1", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X | - IVTV_HW_GPIO, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_GPIO, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER | - IVTV_HW_UPD64031A | IVTV_HW_UPD6408X, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO2 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0xe080, .initial_value = 0x8000 }, - .gpio_audio_input = { .mask = 0x8080, .tuner = 0x8000, .linein = 0x0080 }, - .gpio_audio_mute = { .mask = 0x6000, .mute = 0x6000 }, - .gpio_audio_mode = { .mask = 0x4300, .mono = 0x4000, .stereo = 0x0200, - .lang1 = 0x0300, .lang2 = 0x0000, .both = 0x0200 }, - .gpio_video_input = { .mask = 0x0030, .tuner = 0x0000, - .composite = 0x0010, .svideo = 0x0020}, - .tuners = { - { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 }, - }, - .pci_list = ivtv_pci_dctmvtvp1, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Yuan PG600-2/GotView PCI DVD Lite cards */ - -static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW2, 0x0600 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_pg600v2 = { - .type = IVTV_CARD_PG600V2, - .name = "Yuan PG600-2, GotView PCI DVD Lite", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, - /* XC2028 support apparently works for the Yuan, it's still - uncertain whether it also works with the GotView. */ - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - .xceive_pin = 12, - .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, - }, - .pci_list = ivtv_pci_pg600v2, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Club3D ZAP-TV1x01 cards */ - -static const struct ivtv_card_pci_info ivtv_pci_club3d[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3, 0x0600 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_club3d = { - .type = IVTV_CARD_CLUB3D, - .name = "Club3D ZAP-TV1x01", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - .xceive_pin = 12, - .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, - }, - .pci_list = ivtv_pci_club3d, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* AVerTV MCE 116 Plus (M116) card */ - -static const struct ivtv_card_pci_info ivtv_pci_avertv_mce116[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc439 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_avertv_mce116 = { - .type = IVTV_CARD_AVERTV_MCE116, - .name = "AVerTV MCE 116 Plus", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739 | - IVTV_HW_I2C_IR_RX_AVER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - /* enable line-in */ - .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, - .xceive_pin = 10, - .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, - }, - .pci_list = ivtv_pci_avertv_mce116, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* AVerMedia PVR-150 Plus / AVerTV M113 cards with a Daewoo/Partsnic Tuner */ - -static const struct ivtv_card_pci_info ivtv_pci_aver_pvr150[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc034 }, /* NTSC */ - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc035 }, /* NTSC FM */ - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_aver_pvr150 = { - .type = IVTV_CARD_AVER_PVR150PLUS, - .name = "AVerMedia PVR-150 Plus / AVerTV M113 Partsnic (Daewoo) Tuner", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_muxer = IVTV_HW_GPIO, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | - IVTV_HW_WM8739 | IVTV_HW_GPIO, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, 0 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, - /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */ - .gpio_init = { .direction = 0xc000, .initial_value = 0 }, - .gpio_audio_input = { .mask = 0xc000, - .tuner = 0x0000, - .linein = 0x4000, - .radio = 0x8000 }, - .tuners = { - /* Subsystem ID's 0xc03[45] have a Partsnic PTI-5NF05 tuner */ - { .std = V4L2_STD_MN, .tuner = TUNER_PARTSNIC_PTI_5NF05 }, - }, - .pci_list = ivtv_pci_aver_pvr150, - /* Subsystem ID 0xc035 has a TEA5767(?) FM tuner, 0xc034 does not */ - .i2c = &ivtv_i2c_radio, -}; - -/* ------------------------------------------------------------------------- */ - -/* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */ - -static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, /* NTSC */ - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc01b }, /* PAL/SECAM */ - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_aver_ultra1500mce = { - .type = IVTV_CARD_AVER_ULTRA1500MCE, - .name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner", - .comment = "For non-NTSC tuners, use the pal= or secam= module options", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_muxer = IVTV_HW_GPIO, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | - IVTV_HW_WM8739 | IVTV_HW_GPIO, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, 0 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, - /* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */ - .gpio_init = { .direction = 0xc000, .initial_value = 0 }, - .gpio_audio_input = { .mask = 0xc000, - .tuner = 0x0000, - .linein = 0x4000, - .radio = 0x8000 }, - .tuners = { - /* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */ - { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, - { .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216MK5 }, - }, - .pci_list = ivtv_pci_aver_ultra1500mce, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* AVerMedia EZMaker PCI Deluxe card */ - -static const struct ivtv_card_pci_info ivtv_pci_aver_ezmaker[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc03f }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_aver_ezmaker = { - .type = IVTV_CARD_AVER_EZMAKER, - .name = "AVerMedia EZMaker PCI Deluxe", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739, - .video_inputs = { - { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 }, - { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 0 }, - }, - .gpio_init = { .direction = 0x4000, .initial_value = 0x4000 }, - /* Does not have a tuner */ - .pci_list = ivtv_pci_aver_ezmaker, -}; - -/* ------------------------------------------------------------------------- */ - -/* ASUS Falcon2 */ - -static const struct ivtv_card_pci_info ivtv_pci_asus_falcon2[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b66 }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x462e }, - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b2e }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_asus_falcon2 = { - .type = IVTV_CARD_ASUS_FALCON2, - .name = "ASUS Falcon2", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_muxer = IVTV_HW_M52790, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_M52790 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, CX25840_SVIDEO3 }, - { IVTV_CARD_INPUT_COMPOSITE1, 2, CX25840_COMPOSITE2 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, M52790_IN_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, - M52790_IN_V2 | M52790_SW1_YCMIX | M52790_SW2_YCMIX }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, M52790_IN_V2 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER }, - .tuners = { - { .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 }, - }, - .pci_list = ivtv_pci_asus_falcon2, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* AVerMedia M104 miniPCI card */ - -static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_aver_m104 = { - .type = IVTV_CARD_AVER_M104, - .name = "AVerMedia M104", - .comment = "Not yet supported!\n", - .v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/ - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739, - .video_inputs = { - { IVTV_CARD_INPUT_SVIDEO1, 0, CX25840_SVIDEO3 }, - { IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, 1 }, - }, - .radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 }, - /* enable line-in + reset tuner */ - .gpio_init = { .direction = 0xe000, .initial_value = 0x4000 }, - .xceive_pin = 10, - .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, - }, - .pci_list = ivtv_pci_aver_m104, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ - -/* Buffalo PC-MV5L/PCI cards */ - -static const struct ivtv_card_pci_info ivtv_pci_buffalo[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x052b }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_buffalo = { - .type = IVTV_CARD_BUFFALO_MV5L, - .name = "Buffalo PC-MV5L/PCI", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_CX25840, - .hw_audio = IVTV_HW_CX25840, - .hw_audio_ctrl = IVTV_HW_CX25840, - .hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, CX25840_COMPOSITE2 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, - CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 }, - { IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL }, - }, - .xceive_pin = 12, - .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, - }, - .pci_list = ivtv_pci_buffalo, - .i2c = &ivtv_i2c_std, -}; - -/* ------------------------------------------------------------------------- */ -/* Sony Kikyou */ - -static const struct ivtv_card_pci_info ivtv_pci_kikyou[] = { - { PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_SONY, 0x813d }, - { 0, 0, 0 } -}; - -static const struct ivtv_card ivtv_card_kikyou = { - .type = IVTV_CARD_KIKYOU, - .name = "Sony VAIO Giga Pocket (ENX Kikyou)", - .v4l2_capabilities = IVTV_CAP_ENCODER, - .hw_video = IVTV_HW_SAA7115, - .hw_audio = IVTV_HW_GPIO, - .hw_audio_ctrl = IVTV_HW_GPIO, - .hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER, - .video_inputs = { - { IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_COMPOSITE1 }, - { IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE1 }, - { IVTV_CARD_INPUT_SVIDEO1, 1, IVTV_SAA71XX_SVIDEO1 }, - }, - .audio_inputs = { - { IVTV_CARD_INPUT_AUD_TUNER, IVTV_GPIO_TUNER }, - { IVTV_CARD_INPUT_LINE_IN1, IVTV_GPIO_LINE_IN }, - { IVTV_CARD_INPUT_LINE_IN2, IVTV_GPIO_LINE_IN }, - }, - .gpio_init = { .direction = 0x03e1, .initial_value = 0x0320 }, - .gpio_audio_input = { .mask = 0x0060, - .tuner = 0x0020, - .linein = 0x0000, - .radio = 0x0060 }, - .gpio_audio_mute = { .mask = 0x0000, - .mute = 0x0000 }, /* 0x200? Disable for now. */ - .gpio_audio_mode = { .mask = 0x0080, - .mono = 0x0000, - .stereo = 0x0000, /* SAP */ - .lang1 = 0x0080, - .lang2 = 0x0000, - .both = 0x0080 }, - .tuners = { - { .std = V4L2_STD_ALL, .tuner = TUNER_SONY_BTF_PXN01Z }, - }, - .pci_list = ivtv_pci_kikyou, - .i2c = &ivtv_i2c_std, -}; - - -static const struct ivtv_card *ivtv_card_list[] = { - &ivtv_card_pvr250, - &ivtv_card_pvr350, - &ivtv_card_pvr150, - &ivtv_card_m179, - &ivtv_card_mpg600, - &ivtv_card_mpg160, - &ivtv_card_pg600, - &ivtv_card_avc2410, - &ivtv_card_avc2010, - &ivtv_card_tg5000tv, - &ivtv_card_va2000, - &ivtv_card_cx23416gyc, - &ivtv_card_gv_mvprx, - &ivtv_card_gv_mvprx2e, - &ivtv_card_gotview_pci_dvd, - &ivtv_card_gotview_pci_dvd2, - &ivtv_card_yuan_mpc622, - &ivtv_card_dctmvtvp1, - &ivtv_card_pg600v2, - &ivtv_card_club3d, - &ivtv_card_avertv_mce116, - &ivtv_card_asus_falcon2, - &ivtv_card_aver_pvr150, - &ivtv_card_aver_ezmaker, - &ivtv_card_aver_m104, - &ivtv_card_buffalo, - &ivtv_card_aver_ultra1500mce, - &ivtv_card_kikyou, - - /* Variations of standard cards but with the same PCI IDs. - These cards must come last in this list. */ - &ivtv_card_pvr350_v1, - &ivtv_card_cx23416gyc_nogr, - &ivtv_card_cx23416gyc_nogrycs, -}; - -const struct ivtv_card *ivtv_get_card(u16 index) -{ - if (index >= ARRAY_SIZE(ivtv_card_list)) - return NULL; - return ivtv_card_list[index]; -} - -int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input) -{ - const struct ivtv_card_video_input *card_input = itv->card->video_inputs + index; - static const char * const input_strs[] = { - "Tuner 1", - "S-Video 1", - "S-Video 2", - "Composite 1", - "Composite 2", - "Composite 3" - }; - - if (index >= itv->nof_inputs) - return -EINVAL; - input->index = index; - strlcpy(input->name, input_strs[card_input->video_type - 1], - sizeof(input->name)); - input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ? - V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA); - input->audioset = (1 << itv->nof_audio_inputs) - 1; - input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ? - itv->tuner_std : V4L2_STD_ALL; - return 0; -} - -int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output) -{ - const struct ivtv_card_output *card_output = itv->card->video_outputs + index; - - if (index >= itv->card->nof_outputs) - return -EINVAL; - output->index = index; - strlcpy(output->name, card_output->name, sizeof(output->name)); - output->type = V4L2_OUTPUT_TYPE_ANALOG; - output->audioset = 1; - output->std = V4L2_STD_ALL; - return 0; -} - -int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio) -{ - const struct ivtv_card_audio_input *aud_input = itv->card->audio_inputs + index; - static const char * const input_strs[] = { - "Tuner 1", - "Line In 1", - "Line In 2" - }; - - memset(audio, 0, sizeof(*audio)); - if (index >= itv->nof_audio_inputs) - return -EINVAL; - strlcpy(audio->name, input_strs[aud_input->audio_type - 1], - sizeof(audio->name)); - audio->index = index; - audio->capability = V4L2_AUDCAP_STEREO; - return 0; -} - -int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud_output) -{ - memset(aud_output, 0, sizeof(*aud_output)); - if (itv->card->video_outputs == NULL || index != 0) - return -EINVAL; - strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name)); - return 0; -} diff --git a/drivers/media/video/ivtv/ivtv-cards.h b/drivers/media/video/ivtv/ivtv-cards.h deleted file mode 100644 index e6f5c02981f1..000000000000 --- a/drivers/media/video/ivtv/ivtv-cards.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - Functions to query card hardware - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_CARDS_H -#define IVTV_CARDS_H - -/* Supported cards */ -#define IVTV_CARD_PVR_250 0 /* WinTV PVR 250 */ -#define IVTV_CARD_PVR_350 1 /* encoder, decoder, tv-out */ -#define IVTV_CARD_PVR_150 2 /* WinTV PVR 150 and PVR 500 (really just two - PVR150s on one PCI board) */ -#define IVTV_CARD_M179 3 /* AVerMedia M179 (encoder only) */ -#define IVTV_CARD_MPG600 4 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */ -#define IVTV_CARD_MPG160 5 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160 - cx23415 based, but does not have tv-out */ -#define IVTV_CARD_PG600 6 /* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */ -#define IVTV_CARD_AVC2410 7 /* Adaptec AVC-2410 */ -#define IVTV_CARD_AVC2010 8 /* Adaptec AVD-2010 (No Tuner) */ -#define IVTV_CARD_TG5000TV 9 /* NAGASE TRANSGEAR 5000TV, encoder only */ -#define IVTV_CARD_VA2000MAX_SNT6 10 /* VA2000MAX-STN6 */ -#define IVTV_CARD_CX23416GYC 11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ -#define IVTV_CARD_GV_MVPRX 12 /* I/O Data GV-MVP/RX, RX2, RX2W */ -#define IVTV_CARD_GV_MVPRX2E 13 /* I/O Data GV-MVP/RX2E */ -#define IVTV_CARD_GOTVIEW_PCI_DVD 14 /* GotView PCI DVD */ -#define IVTV_CARD_GOTVIEW_PCI_DVD2 15 /* GotView PCI DVD2 */ -#define IVTV_CARD_YUAN_MPC622 16 /* Yuan MPC622 miniPCI */ -#define IVTV_CARD_DCTMTVP1 17 /* DIGITAL COWBOY DCT-MTVP1 */ -#define IVTV_CARD_PG600V2 18 /* Yuan PG600V2/GotView PCI DVD Lite */ -#define IVTV_CARD_CLUB3D 19 /* Club3D ZAP-TV1x01 */ -#define IVTV_CARD_AVERTV_MCE116 20 /* AVerTV MCE 116 Plus */ -#define IVTV_CARD_ASUS_FALCON2 21 /* ASUS Falcon2 */ -#define IVTV_CARD_AVER_PVR150PLUS 22 /* AVerMedia PVR-150 Plus */ -#define IVTV_CARD_AVER_EZMAKER 23 /* AVerMedia EZMaker PCI Deluxe */ -#define IVTV_CARD_AVER_M104 24 /* AverMedia M104 miniPCI card */ -#define IVTV_CARD_BUFFALO_MV5L 25 /* Buffalo PC-MV5L/PCI card */ -#define IVTV_CARD_AVER_ULTRA1500MCE 26 /* AVerMedia UltraTV 1500 MCE */ -#define IVTV_CARD_KIKYOU 27 /* Sony VAIO Giga Pocket (ENX Kikyou) */ -#define IVTV_CARD_LAST 27 - -/* Variants of existing cards but with the same PCI IDs. The driver - detects these based on other device information. - These cards must always come last. - New cards must be inserted above, and the indices of the cards below - must be adjusted accordingly. */ - -/* PVR-350 V1 (uses saa7114) */ -#define IVTV_CARD_PVR_350_V1 (IVTV_CARD_LAST+1) -/* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */ -#define IVTV_CARD_CX23416GYC_NOGR (IVTV_CARD_LAST+2) -#define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3) - -/* system vendor and device IDs */ -#define PCI_VENDOR_ID_ICOMP 0x4444 -#define PCI_DEVICE_ID_IVTV15 0x0803 -#define PCI_DEVICE_ID_IVTV16 0x0016 - -/* subsystem vendor ID */ -#define IVTV_PCI_ID_HAUPPAUGE 0x0070 -#define IVTV_PCI_ID_HAUPPAUGE_ALT1 0x0270 -#define IVTV_PCI_ID_HAUPPAUGE_ALT2 0x4070 -#define IVTV_PCI_ID_ADAPTEC 0x9005 -#define IVTV_PCI_ID_ASUSTEK 0x1043 -#define IVTV_PCI_ID_AVERMEDIA 0x1461 -#define IVTV_PCI_ID_YUAN1 0x12ab -#define IVTV_PCI_ID_YUAN2 0xff01 -#define IVTV_PCI_ID_YUAN3 0xffab -#define IVTV_PCI_ID_YUAN4 0xfbab -#define IVTV_PCI_ID_DIAMONDMM 0xff92 -#define IVTV_PCI_ID_IODATA 0x10fc -#define IVTV_PCI_ID_MELCO 0x1154 -#define IVTV_PCI_ID_GOTVIEW1 0xffac -#define IVTV_PCI_ID_GOTVIEW2 0xffad -#define IVTV_PCI_ID_SONY 0x104d - -/* hardware flags, no gaps allowed */ -#define IVTV_HW_CX25840 (1 << 0) -#define IVTV_HW_SAA7115 (1 << 1) -#define IVTV_HW_SAA7127 (1 << 2) -#define IVTV_HW_MSP34XX (1 << 3) -#define IVTV_HW_TUNER (1 << 4) -#define IVTV_HW_WM8775 (1 << 5) -#define IVTV_HW_CS53L32A (1 << 6) -#define IVTV_HW_TVEEPROM (1 << 7) -#define IVTV_HW_SAA7114 (1 << 8) -#define IVTV_HW_UPD64031A (1 << 9) -#define IVTV_HW_UPD6408X (1 << 10) -#define IVTV_HW_SAA717X (1 << 11) -#define IVTV_HW_WM8739 (1 << 12) -#define IVTV_HW_VP27SMPX (1 << 13) -#define IVTV_HW_M52790 (1 << 14) -#define IVTV_HW_GPIO (1 << 15) -#define IVTV_HW_I2C_IR_RX_AVER (1 << 16) -#define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */ -#define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18) -#define IVTV_HW_Z8F0811_IR_TX_HAUP (1 << 19) -#define IVTV_HW_Z8F0811_IR_RX_HAUP (1 << 20) -#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 21) - -#define IVTV_HW_Z8F0811_IR_HAUP (IVTV_HW_Z8F0811_IR_RX_HAUP | \ - IVTV_HW_Z8F0811_IR_TX_HAUP) - -#define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114) - -#define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \ - IVTV_HW_I2C_IR_RX_HAUP_EXT | \ - IVTV_HW_I2C_IR_RX_HAUP_INT | \ - IVTV_HW_Z8F0811_IR_RX_HAUP | \ - IVTV_HW_I2C_IR_RX_ADAPTEC) - -#define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP) - -#define IVTV_HW_IR_ANY (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY) - -/* video inputs */ -#define IVTV_CARD_INPUT_VID_TUNER 1 -#define IVTV_CARD_INPUT_SVIDEO1 2 -#define IVTV_CARD_INPUT_SVIDEO2 3 -#define IVTV_CARD_INPUT_COMPOSITE1 4 -#define IVTV_CARD_INPUT_COMPOSITE2 5 -#define IVTV_CARD_INPUT_COMPOSITE3 6 - -/* audio inputs */ -#define IVTV_CARD_INPUT_AUD_TUNER 1 -#define IVTV_CARD_INPUT_LINE_IN1 2 -#define IVTV_CARD_INPUT_LINE_IN2 3 - -#define IVTV_CARD_MAX_VIDEO_INPUTS 6 -#define IVTV_CARD_MAX_AUDIO_INPUTS 3 -#define IVTV_CARD_MAX_TUNERS 3 - -/* SAA71XX HW inputs */ -#define IVTV_SAA71XX_COMPOSITE0 0 -#define IVTV_SAA71XX_COMPOSITE1 1 -#define IVTV_SAA71XX_COMPOSITE2 2 -#define IVTV_SAA71XX_COMPOSITE3 3 -#define IVTV_SAA71XX_COMPOSITE4 4 -#define IVTV_SAA71XX_COMPOSITE5 5 -#define IVTV_SAA71XX_SVIDEO0 6 -#define IVTV_SAA71XX_SVIDEO1 7 -#define IVTV_SAA71XX_SVIDEO2 8 -#define IVTV_SAA71XX_SVIDEO3 9 - -/* SAA717X needs to mark the tuner input by ORing with this flag */ -#define IVTV_SAA717X_TUNER_FLAG 0x80 - -/* Dummy HW input */ -#define IVTV_DUMMY_AUDIO 0 - -/* GPIO HW inputs */ -#define IVTV_GPIO_TUNER 0 -#define IVTV_GPIO_LINE_IN 1 - -/* SAA717X HW inputs */ -#define IVTV_SAA717X_IN0 0 -#define IVTV_SAA717X_IN1 1 -#define IVTV_SAA717X_IN2 2 - -/* V4L2 capability aliases */ -#define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ - V4L2_CAP_SLICED_VBI_CAPTURE) -#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \ - V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY) - -struct ivtv_card_video_input { - u8 video_type; /* video input type */ - u8 audio_index; /* index in ivtv_card_audio_input array */ - u16 video_input; /* hardware video input */ -}; - -struct ivtv_card_audio_input { - u8 audio_type; /* audio input type */ - u32 audio_input; /* hardware audio input */ - u16 muxer_input; /* hardware muxer input for boards with a - multiplexer chip */ -}; - -struct ivtv_card_output { - u8 name[32]; - u16 video_output; /* hardware video output */ -}; - -struct ivtv_card_pci_info { - u16 device; - u16 subsystem_vendor; - u16 subsystem_device; -}; - -/* GPIO definitions */ - -/* The mask is the set of bits used by the operation */ - -struct ivtv_gpio_init { /* set initial GPIO DIR and OUT values */ - u16 direction; /* DIR setting. Leave to 0 if no init is needed */ - u16 initial_value; -}; - -struct ivtv_gpio_video_input { /* select tuner/line in input */ - u16 mask; /* leave to 0 if not supported */ - u16 tuner; - u16 composite; - u16 svideo; -}; - -struct ivtv_gpio_audio_input { /* select tuner/line in input */ - u16 mask; /* leave to 0 if not supported */ - u16 tuner; - u16 linein; - u16 radio; -}; - -struct ivtv_gpio_audio_mute { - u16 mask; /* leave to 0 if not supported */ - u16 mute; /* set this value to mute, 0 to unmute */ -}; - -struct ivtv_gpio_audio_mode { - u16 mask; /* leave to 0 if not supported */ - u16 mono; /* set audio to mono */ - u16 stereo; /* set audio to stereo */ - u16 lang1; /* set audio to the first language */ - u16 lang2; /* set audio to the second language */ - u16 both; /* both languages are output */ -}; - -struct ivtv_gpio_audio_freq { - u16 mask; /* leave to 0 if not supported */ - u16 f32000; - u16 f44100; - u16 f48000; -}; - -struct ivtv_gpio_audio_detect { - u16 mask; /* leave to 0 if not supported */ - u16 stereo; /* if the input matches this value then - stereo is detected */ -}; - -struct ivtv_card_tuner { - v4l2_std_id std; /* standard for which the tuner is suitable */ - int tuner; /* tuner ID (from tuner.h) */ -}; - -struct ivtv_card_tuner_i2c { - unsigned short radio[2];/* radio tuner i2c address to probe */ - unsigned short demod[2];/* demodulator i2c address to probe */ - unsigned short tv[4]; /* tv tuner i2c addresses to probe */ -}; - -/* for card information/parameters */ -struct ivtv_card { - int type; - char *name; - char *comment; - u32 v4l2_capabilities; - u32 hw_video; /* hardware used to process video */ - u32 hw_audio; /* hardware used to process audio */ - u32 hw_audio_ctrl; /* hardware used for the V4L2 controls (only 1 dev allowed) */ - u32 hw_muxer; /* hardware used to multiplex audio input */ - u32 hw_all; /* all hardware used by the board */ - struct ivtv_card_video_input video_inputs[IVTV_CARD_MAX_VIDEO_INPUTS]; - struct ivtv_card_audio_input audio_inputs[IVTV_CARD_MAX_AUDIO_INPUTS]; - struct ivtv_card_audio_input radio_input; - int nof_outputs; - const struct ivtv_card_output *video_outputs; - u8 gr_config; /* config byte for the ghost reduction device */ - u8 xceive_pin; /* XCeive tuner GPIO reset pin */ - - /* GPIO card-specific settings */ - struct ivtv_gpio_init gpio_init; - struct ivtv_gpio_video_input gpio_video_input; - struct ivtv_gpio_audio_input gpio_audio_input; - struct ivtv_gpio_audio_mute gpio_audio_mute; - struct ivtv_gpio_audio_mode gpio_audio_mode; - struct ivtv_gpio_audio_freq gpio_audio_freq; - struct ivtv_gpio_audio_detect gpio_audio_detect; - - struct ivtv_card_tuner tuners[IVTV_CARD_MAX_TUNERS]; - struct ivtv_card_tuner_i2c *i2c; - - /* list of device and subsystem vendor/devices that - correspond to this card type. */ - const struct ivtv_card_pci_info *pci_list; -}; - -int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input); -int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output); -int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input); -int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output); -const struct ivtv_card *ivtv_get_card(u16 index); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c deleted file mode 100644 index c60424601cb9..000000000000 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - ioctl control functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-ioctl.h" -#include "ivtv-controls.h" -#include "ivtv-mailbox.h" - -static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt) -{ - struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl); - - /* First try to allocate sliced VBI buffers if needed. */ - if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) { - int i; - - for (i = 0; i < IVTV_VBI_FRAMES; i++) { - /* Yuck, hardcoded. Needs to be a define */ - itv->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL); - if (itv->vbi.sliced_mpeg_data[i] == NULL) { - while (--i >= 0) { - kfree(itv->vbi.sliced_mpeg_data[i]); - itv->vbi.sliced_mpeg_data[i] = NULL; - } - return -ENOMEM; - } - } - } - - itv->vbi.insert_mpeg = fmt; - - if (itv->vbi.insert_mpeg == 0) { - return 0; - } - /* Need sliced data for mpeg insertion */ - if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) { - if (itv->is_60hz) - itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; - else - itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; - ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz); - } - return 0; -} - -static int ivtv_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val) -{ - struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl); - int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; - struct v4l2_mbus_framefmt fmt; - - /* fix videodecoder resolution */ - fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1); - fmt.height = cxhdl->height; - fmt.code = V4L2_MBUS_FMT_FIXED; - v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt); - return 0; -} - -static int ivtv_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx) -{ - static const u32 freqs[3] = { 44100, 48000, 32000 }; - struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl); - - /* The audio clock of the digitizer must match the codec sample - rate otherwise you get some very strange effects. */ - if (idx < ARRAY_SIZE(freqs)) - ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]); - return 0; -} - -static int ivtv_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val) -{ - struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl); - - itv->dualwatch_stereo_mode = val; - return 0; -} - -struct cx2341x_handler_ops ivtv_cxhdl_ops = { - .s_audio_mode = ivtv_s_audio_mode, - .s_audio_sampling_freq = ivtv_s_audio_sampling_freq, - .s_video_encoding = ivtv_s_video_encoding, - .s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt, -}; - -int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - - if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) { - *pts = (s64)((u64)itv->last_dec_timing[2] << 32) | - (u64)itv->last_dec_timing[1]; - *frame = itv->last_dec_timing[0]; - return 0; - } - *pts = 0; - *frame = 0; - if (atomic_read(&itv->decoding)) { - if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) { - IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n"); - return -EIO; - } - memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing)); - set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); - *pts = (s64)((u64) data[2] << 32) | (u64) data[1]; - *frame = data[0]; - /*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/ - } - return 0; -} - -static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl) -{ - struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); - - switch (ctrl->id) { - /* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME - control cluster */ - case V4L2_CID_MPEG_VIDEO_DEC_PTS: - return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64, - &itv->ctrl_frame->val64); - } - return 0; -} - -static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl); - - switch (ctrl->id) { - /* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK - control cluster */ - case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK: - itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1; - itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1; - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - break; - } - return 0; -} - -const struct v4l2_ctrl_ops ivtv_hdl_out_ops = { - .s_ctrl = ivtv_s_ctrl, - .g_volatile_ctrl = ivtv_g_volatile_ctrl, -}; diff --git a/drivers/media/video/ivtv/ivtv-controls.h b/drivers/media/video/ivtv/ivtv-controls.h deleted file mode 100644 index 3999e6358312..000000000000 --- a/drivers/media/video/ivtv/ivtv-controls.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - ioctl control functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_CONTROLS_H -#define IVTV_CONTROLS_H - -extern struct cx2341x_handler_ops ivtv_cxhdl_ops; -extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops; -int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c deleted file mode 100644 index 5462ce2f60ea..000000000000 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ /dev/null @@ -1,1498 +0,0 @@ -/* - ivtv driver initialization and card probing - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Main Driver file for the ivtv project: - * Driver for the Conexant CX23415/CX23416 chip. - * Author: Kevin Thayer (nufan_wfk at yahoo.com) - * License: GPL - * http://www.ivtvdriver.org - * - * ----- - * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> - * and Takeru KOMORIYA<komoriya@paken.org> - * - * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> - * using information provided by Jiun-Kuei Jung @ AVerMedia. - * - * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp> - * using information from T.Adachi,Takeru KOMORIYA and others :-) - * - * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX - * version by T.Adachi. Special thanks Mr.Suzuki - */ - -#include "ivtv-driver.h" -#include "ivtv-version.h" -#include "ivtv-fileops.h" -#include "ivtv-i2c.h" -#include "ivtv-firmware.h" -#include "ivtv-queue.h" -#include "ivtv-udma.h" -#include "ivtv-irq.h" -#include "ivtv-mailbox.h" -#include "ivtv-streams.h" -#include "ivtv-ioctl.h" -#include "ivtv-cards.h" -#include "ivtv-vbi.h" -#include "ivtv-routing.h" -#include "ivtv-controls.h" -#include "ivtv-gpio.h" -#include <linux/dma-mapping.h> -#include <media/tveeprom.h> -#include <media/saa7115.h> -#include <media/v4l2-chip-ident.h> -#include "tuner-xc2028.h" - -/* If you have already X v4l cards, then set this to X. This way - the device numbers stay matched. Example: you have a WinTV card - without radio and a PVR-350 with. Normally this would give a - video1 device together with a radio0 device for the PVR. By - setting this to 1 you ensure that radio0 is now also radio1. */ -int ivtv_first_minor; - -/* add your revision and whatnot here */ -static struct pci_device_id ivtv_pci_tbl[] __devinitdata = { - {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} -}; - -MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl); - -/* ivtv instance counter */ -static atomic_t ivtv_instance = ATOMIC_INIT(0); - -/* Parameter declarations */ -static int cardtype[IVTV_MAX_CARDS]; -static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; -static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; -static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; - -static unsigned int cardtype_c = 1; -static unsigned int tuner_c = 1; -static int radio_c = 1; -static unsigned int i2c_clock_period_c = 1; -static char pal[] = "---"; -static char secam[] = "--"; -static char ntsc[] = "-"; - -/* Buffers */ - -/* DMA Buffers, Default size in MB allocated */ -#define IVTV_DEFAULT_ENC_MPG_BUFFERS 4 -#define IVTV_DEFAULT_ENC_YUV_BUFFERS 2 -#define IVTV_DEFAULT_ENC_VBI_BUFFERS 1 -/* Exception: size in kB for this stream (MB is overkill) */ -#define IVTV_DEFAULT_ENC_PCM_BUFFERS 320 -#define IVTV_DEFAULT_DEC_MPG_BUFFERS 1 -#define IVTV_DEFAULT_DEC_YUV_BUFFERS 1 -/* Exception: size in kB for this stream (MB is way overkill) */ -#define IVTV_DEFAULT_DEC_VBI_BUFFERS 64 - -static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS; -static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS; -static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS; -static int enc_pcm_buffers = IVTV_DEFAULT_ENC_PCM_BUFFERS; -static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS; -static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS; -static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS; - -static int ivtv_yuv_mode; -static int ivtv_yuv_threshold = -1; -static int ivtv_pci_latency = 1; - -int ivtv_debug; -#ifdef CONFIG_VIDEO_ADV_DEBUG -int ivtv_fw_debug; -#endif - -static int tunertype = -1; -static int newi2c = -1; - -module_param_array(tuner, int, &tuner_c, 0644); -module_param_array(radio, int, &radio_c, 0644); -module_param_array(cardtype, int, &cardtype_c, 0644); -module_param_string(pal, pal, sizeof(pal), 0644); -module_param_string(secam, secam, sizeof(secam), 0644); -module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); -module_param_named(debug,ivtv_debug, int, 0644); -#ifdef CONFIG_VIDEO_ADV_DEBUG -module_param_named(fw_debug, ivtv_fw_debug, int, 0644); -#endif -module_param(ivtv_pci_latency, int, 0644); -module_param(ivtv_yuv_mode, int, 0644); -module_param(ivtv_yuv_threshold, int, 0644); -module_param(ivtv_first_minor, int, 0644); - -module_param(enc_mpg_buffers, int, 0644); -module_param(enc_yuv_buffers, int, 0644); -module_param(enc_vbi_buffers, int, 0644); -module_param(enc_pcm_buffers, int, 0644); -module_param(dec_mpg_buffers, int, 0644); -module_param(dec_yuv_buffers, int, 0644); -module_param(dec_vbi_buffers, int, 0644); - -module_param(tunertype, int, 0644); -module_param(newi2c, int, 0644); -module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644); - -MODULE_PARM_DESC(tuner, "Tuner type selection,\n" - "\t\t\tsee tuner.h for values"); -MODULE_PARM_DESC(radio, - "Enable or disable the radio. Use only if autodetection\n" - "\t\t\tfails. 0 = disable, 1 = enable"); -MODULE_PARM_DESC(cardtype, - "Only use this option if your card is not detected properly.\n" - "\t\tSpecify card type:\n" - "\t\t\t 1 = WinTV PVR 250\n" - "\t\t\t 2 = WinTV PVR 350\n" - "\t\t\t 3 = WinTV PVR-150 or PVR-500\n" - "\t\t\t 4 = AVerMedia M179\n" - "\t\t\t 5 = YUAN MPG600/Kuroutoshikou iTVC16-STVLP\n" - "\t\t\t 6 = YUAN MPG160/Kuroutoshikou iTVC15-STVLP\n" - "\t\t\t 7 = YUAN PG600/DIAMONDMM PVR-550 (CX Falcon 2)\n" - "\t\t\t 8 = Adaptec AVC-2410\n" - "\t\t\t 9 = Adaptec AVC-2010\n" - "\t\t\t10 = NAGASE TRANSGEAR 5000TV\n" - "\t\t\t11 = AOpen VA2000MAX-STN6\n" - "\t\t\t12 = YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP\n" - "\t\t\t13 = I/O Data GV-MVP/RX\n" - "\t\t\t14 = I/O Data GV-MVP/RX2E\n" - "\t\t\t15 = GOTVIEW PCI DVD\n" - "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n" - "\t\t\t17 = Yuan MPC622\n" - "\t\t\t18 = Digital Cowboy DCT-MTVP1\n" - "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite\n" - "\t\t\t20 = Club3D ZAP-TV1x01\n" - "\t\t\t21 = AverTV MCE 116 Plus\n" - "\t\t\t22 = ASUS Falcon2\n" - "\t\t\t23 = AverMedia PVR-150 Plus\n" - "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n" - "\t\t\t25 = AverMedia M104 (not yet working)\n" - "\t\t\t26 = Buffalo PC-MV5L/PCI\n" - "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n" - "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\n" - "\t\t\t 0 = Autodetect (default)\n" - "\t\t\t-1 = Ignore this card\n\t\t"); -MODULE_PARM_DESC(pal, "Set PAL standard: BGH, DK, I, M, N, Nc, 60"); -MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC"); -MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)"); -MODULE_PARM_DESC(tunertype, - "Specify tuner type:\n" - "\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n" - "\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n" - "\t\t\t-1 = Autodetect (default)\n"); -MODULE_PARM_DESC(debug, - "Debug level (bitmask). Default: 0\n" - "\t\t\t 1/0x0001: warning\n" - "\t\t\t 2/0x0002: info\n" - "\t\t\t 4/0x0004: mailbox\n" - "\t\t\t 8/0x0008: ioctl\n" - "\t\t\t 16/0x0010: file\n" - "\t\t\t 32/0x0020: dma\n" - "\t\t\t 64/0x0040: irq\n" - "\t\t\t 128/0x0080: decoder\n" - "\t\t\t 256/0x0100: yuv\n" - "\t\t\t 512/0x0200: i2c\n" - "\t\t\t1024/0x0400: high volume\n"); -#ifdef CONFIG_VIDEO_ADV_DEBUG -MODULE_PARM_DESC(fw_debug, - "Enable code for debugging firmware problems. Default: 0\n"); -#endif -MODULE_PARM_DESC(ivtv_pci_latency, - "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" - "\t\t\tDefault: Yes"); -MODULE_PARM_DESC(ivtv_yuv_mode, - "Specify the yuv playback mode:\n" - "\t\t\t0 = interlaced\n\t\t\t1 = progressive\n\t\t\t2 = auto\n" - "\t\t\tDefault: 0 (interlaced)"); -MODULE_PARM_DESC(ivtv_yuv_threshold, - "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n" - "\t\t\tDefault: 480"); -MODULE_PARM_DESC(enc_mpg_buffers, - "Encoder MPG Buffers (in MB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS)); -MODULE_PARM_DESC(enc_yuv_buffers, - "Encoder YUV Buffers (in MB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_YUV_BUFFERS)); -MODULE_PARM_DESC(enc_vbi_buffers, - "Encoder VBI Buffers (in MB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS)); -MODULE_PARM_DESC(enc_pcm_buffers, - "Encoder PCM buffers (in kB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS)); -MODULE_PARM_DESC(dec_mpg_buffers, - "Decoder MPG buffers (in MB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_MPG_BUFFERS)); -MODULE_PARM_DESC(dec_yuv_buffers, - "Decoder YUV buffers (in MB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS)); -MODULE_PARM_DESC(dec_vbi_buffers, - "Decoder VBI buffers (in kB)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS)); -MODULE_PARM_DESC(newi2c, - "Use new I2C implementation\n" - "\t\t\t-1 is autodetect, 0 is off, 1 is on\n" - "\t\t\tDefault is autodetect"); -MODULE_PARM_DESC(i2c_clock_period, - "Period of SCL for the I2C bus controlled by the CX23415/6\n" - "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n" - "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD)); - -MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card"); - -MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil"); -MODULE_DESCRIPTION("CX23415/CX23416 driver"); -MODULE_SUPPORTED_DEVICE - ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n" - "\t\t\tYuan MPG series and similar)"); -MODULE_LICENSE("GPL"); - -MODULE_VERSION(IVTV_VERSION); - -void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask) -{ - itv->irqmask &= ~mask; - write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK); -} - -void ivtv_set_irq_mask(struct ivtv *itv, u32 mask) -{ - itv->irqmask |= mask; - write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK); -} - -int ivtv_set_output_mode(struct ivtv *itv, int mode) -{ - int old_mode; - - spin_lock(&itv->lock); - old_mode = itv->output_mode; - if (old_mode == 0) - itv->output_mode = old_mode = mode; - spin_unlock(&itv->lock); - return old_mode; -} - -struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv) -{ - switch (itv->output_mode) { - case OUT_MPG: - return &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; - case OUT_YUV: - return &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; - default: - return NULL; - } -} - -int ivtv_waitq(wait_queue_head_t *waitq) -{ - DEFINE_WAIT(wait); - - prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE); - schedule(); - finish_wait(waitq, &wait); - return signal_pending(current) ? -EINTR : 0; -} - -/* Generic utility functions */ -int ivtv_msleep_timeout(unsigned int msecs, int intr) -{ - int timeout = msecs_to_jiffies(msecs); - - do { - set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); - timeout = schedule_timeout(timeout); - if (intr) { - int ret = signal_pending(current); - - if (ret) - return ret; - } - } while (timeout); - return 0; -} - -/* Release ioremapped memory */ -static void ivtv_iounmap(struct ivtv *itv) -{ - if (itv == NULL) - return; - - /* Release registers memory */ - if (itv->reg_mem != NULL) { - IVTV_DEBUG_INFO("releasing reg_mem\n"); - iounmap(itv->reg_mem); - itv->reg_mem = NULL; - } - /* Release io memory */ - if (itv->has_cx23415 && itv->dec_mem != NULL) { - IVTV_DEBUG_INFO("releasing dec_mem\n"); - iounmap(itv->dec_mem); - } - itv->dec_mem = NULL; - - /* Release io memory */ - if (itv->enc_mem != NULL) { - IVTV_DEBUG_INFO("releasing enc_mem\n"); - iounmap(itv->enc_mem); - itv->enc_mem = NULL; - } -} - -/* Hauppauge card? get values from tveeprom */ -void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) -{ - u8 eedata[256]; - - itv->i2c_client.addr = 0xA0 >> 1; - tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata)); - tveeprom_hauppauge_analog(&itv->i2c_client, tv, eedata); -} - -static void ivtv_process_eeprom(struct ivtv *itv) -{ - struct tveeprom tv; - int pci_slot = PCI_SLOT(itv->pdev->devfn); - - ivtv_read_eeprom(itv, &tv); - - /* Many thanks to Steven Toth from Hauppauge for providing the - model numbers */ - switch (tv.model) { - /* In a few cases the PCI subsystem IDs do not correctly - identify the card. A better method is to check the - model number from the eeprom instead. */ - case 30012 ... 30039: /* Low profile PVR250 */ - case 32000 ... 32999: - case 48000 ... 48099: /* 48??? range are PVR250s with a cx23415 */ - case 48400 ... 48599: - itv->card = ivtv_get_card(IVTV_CARD_PVR_250); - break; - case 48100 ... 48399: - case 48600 ... 48999: - itv->card = ivtv_get_card(IVTV_CARD_PVR_350); - break; - case 23000 ... 23999: /* PVR500 */ - case 25000 ... 25999: /* Low profile PVR150 */ - case 26000 ... 26999: /* Regular PVR150 */ - itv->card = ivtv_get_card(IVTV_CARD_PVR_150); - break; - case 0: - IVTV_ERR("Invalid EEPROM\n"); - return; - default: - IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model); - itv->card = ivtv_get_card(IVTV_CARD_PVR_150); - break; - } - - switch (tv.model) { - /* Old style PVR350 (with an saa7114) uses this input for - the tuner. */ - case 48254: - itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1); - break; - default: - break; - } - - itv->v4l2_cap = itv->card->v4l2_capabilities; - itv->card_name = itv->card->name; - itv->card_i2c = itv->card->i2c; - - /* If this is a PVR500 then it should be possible to detect whether it is the - first or second unit by looking at the subsystem device ID: is bit 4 is - set, then it is the second unit (according to info from Hauppauge). - - However, while this works for most cards, I have seen a few PVR500 cards - where both units have the same subsystem ID. - - So instead I look at the reported 'PCI slot' (which is the slot on the PVR500 - PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise - it is the second unit. It is possible that it is a different slot when ivtv is - used in Xen, in that case I ignore this card here. The worst that can happen - is that the card presents itself with a non-working radio device. - - This detection is needed since the eeprom reports incorrectly that a radio is - present on the second unit. */ - if (tv.model / 1000 == 23) { - static const struct ivtv_card_tuner_i2c ivtv_i2c_radio = { - .radio = { 0x60, I2C_CLIENT_END }, - .demod = { 0x43, I2C_CLIENT_END }, - .tv = { 0x61, I2C_CLIENT_END }, - }; - - itv->card_name = "WinTV PVR 500"; - itv->card_i2c = &ivtv_i2c_radio; - if (pci_slot == 8 || pci_slot == 9) { - int is_first = (pci_slot & 1) == 0; - - itv->card_name = is_first ? "WinTV PVR 500 (unit #1)" : - "WinTV PVR 500 (unit #2)"; - if (!is_first) { - IVTV_INFO("Correcting tveeprom data: no radio present on second unit\n"); - tv.has_radio = 0; - } - } - } - IVTV_INFO("Autodetected %s\n", itv->card_name); - - switch (tv.tuner_hauppauge_model) { - case 85: - case 99: - case 112: - itv->pvr150_workaround = 1; - break; - default: - break; - } - if (tv.tuner_type == TUNER_ABSENT) - IVTV_ERR("tveeprom cannot autodetect tuner!\n"); - - if (itv->options.tuner == -1) - itv->options.tuner = tv.tuner_type; - if (itv->options.radio == -1) - itv->options.radio = (tv.has_radio != 0); - /* only enable newi2c if an IR blaster is present */ - if (itv->options.newi2c == -1 && tv.has_ir) { - itv->options.newi2c = (tv.has_ir & 4) ? 1 : 0; - if (itv->options.newi2c) { - IVTV_INFO("Reopen i2c bus for IR-blaster support\n"); - exit_ivtv_i2c(itv); - init_ivtv_i2c(itv); - } - } - - if (itv->std != 0) - /* user specified tuner standard */ - return; - - /* autodetect tuner standard */ - if (tv.tuner_formats & V4L2_STD_PAL) { - IVTV_DEBUG_INFO("PAL tuner detected\n"); - itv->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H; - } else if (tv.tuner_formats & V4L2_STD_NTSC) { - IVTV_DEBUG_INFO("NTSC tuner detected\n"); - itv->std |= V4L2_STD_NTSC_M; - } else if (tv.tuner_formats & V4L2_STD_SECAM) { - IVTV_DEBUG_INFO("SECAM tuner detected\n"); - itv->std |= V4L2_STD_SECAM_L; - } else { - IVTV_INFO("No tuner detected, default to NTSC-M\n"); - itv->std |= V4L2_STD_NTSC_M; - } -} - -static v4l2_std_id ivtv_parse_std(struct ivtv *itv) -{ - switch (pal[0]) { - case '6': - tunertype = 0; - return V4L2_STD_PAL_60; - case 'b': - case 'B': - case 'g': - case 'G': - case 'h': - case 'H': - tunertype = 0; - return V4L2_STD_PAL_BG | V4L2_STD_PAL_H; - case 'n': - case 'N': - tunertype = 1; - if (pal[1] == 'c' || pal[1] == 'C') - return V4L2_STD_PAL_Nc; - return V4L2_STD_PAL_N; - case 'i': - case 'I': - tunertype = 0; - return V4L2_STD_PAL_I; - case 'd': - case 'D': - case 'k': - case 'K': - tunertype = 0; - return V4L2_STD_PAL_DK; - case 'M': - case 'm': - tunertype = 1; - return V4L2_STD_PAL_M; - case '-': - break; - default: - IVTV_WARN("pal= argument not recognised\n"); - return 0; - } - - switch (secam[0]) { - case 'b': - case 'B': - case 'g': - case 'G': - case 'h': - case 'H': - tunertype = 0; - return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; - case 'd': - case 'D': - case 'k': - case 'K': - tunertype = 0; - return V4L2_STD_SECAM_DK; - case 'l': - case 'L': - tunertype = 0; - if (secam[1] == 'C' || secam[1] == 'c') - return V4L2_STD_SECAM_LC; - return V4L2_STD_SECAM_L; - case '-': - break; - default: - IVTV_WARN("secam= argument not recognised\n"); - return 0; - } - - switch (ntsc[0]) { - case 'm': - case 'M': - tunertype = 1; - return V4L2_STD_NTSC_M; - case 'j': - case 'J': - tunertype = 1; - return V4L2_STD_NTSC_M_JP; - case 'k': - case 'K': - tunertype = 1; - return V4L2_STD_NTSC_M_KR; - case '-': - break; - default: - IVTV_WARN("ntsc= argument not recognised\n"); - return 0; - } - - /* no match found */ - return 0; -} - -static void ivtv_process_options(struct ivtv *itv) -{ - const char *chipname; - int i, j; - - itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers * 1024; - itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers * 1024; - itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers * 1024; - itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers; - itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024; - itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024; - itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers; - itv->options.cardtype = cardtype[itv->instance]; - itv->options.tuner = tuner[itv->instance]; - itv->options.radio = radio[itv->instance]; - - itv->options.i2c_clock_period = i2c_clock_period[itv->instance]; - if (itv->options.i2c_clock_period == -1) - itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD; - else if (itv->options.i2c_clock_period < 10) - itv->options.i2c_clock_period = 10; - else if (itv->options.i2c_clock_period > 4500) - itv->options.i2c_clock_period = 4500; - - itv->options.newi2c = newi2c; - if (tunertype < -1 || tunertype > 1) { - IVTV_WARN("Invalid tunertype argument, will autodetect instead\n"); - tunertype = -1; - } - itv->std = ivtv_parse_std(itv); - if (itv->std == 0 && tunertype >= 0) - itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN); - itv->has_cx23415 = (itv->pdev->device == PCI_DEVICE_ID_IVTV15); - chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; - if (itv->options.cardtype == -1) { - IVTV_INFO("Ignore card (detected %s based chip)\n", chipname); - return; - } - if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) { - IVTV_INFO("User specified %s card (detected %s based chip)\n", - itv->card->name, chipname); - } else if (itv->options.cardtype != 0) { - IVTV_ERR("Unknown user specified type, trying to autodetect card\n"); - } - if (itv->card == NULL) { - if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE || - itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 || - itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) { - itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150); - IVTV_INFO("Autodetected Hauppauge card (%s based)\n", - chipname); - } - } - if (itv->card == NULL) { - for (i = 0; (itv->card = ivtv_get_card(i)); i++) { - if (itv->card->pci_list == NULL) - continue; - for (j = 0; itv->card->pci_list[j].device; j++) { - if (itv->pdev->device != - itv->card->pci_list[j].device) - continue; - if (itv->pdev->subsystem_vendor != - itv->card->pci_list[j].subsystem_vendor) - continue; - if (itv->pdev->subsystem_device != - itv->card->pci_list[j].subsystem_device) - continue; - IVTV_INFO("Autodetected %s card (%s based)\n", - itv->card->name, chipname); - goto done; - } - } - } -done: - - if (itv->card == NULL) { - itv->card = ivtv_get_card(IVTV_CARD_PVR_150); - IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n", - itv->pdev->vendor, itv->pdev->device); - IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n", - itv->pdev->subsystem_vendor, itv->pdev->subsystem_device); - IVTV_ERR(" %s based\n", chipname); - IVTV_ERR("Defaulting to %s card\n", itv->card->name); - IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n"); - IVTV_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n"); - IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n"); - } - itv->v4l2_cap = itv->card->v4l2_capabilities; - itv->card_name = itv->card->name; - itv->card_i2c = itv->card->i2c; -} - -/* Precondition: the ivtv structure has been memset to 0. Only - the dev and num fields have been filled in. - No assumptions on the card type may be made here (see ivtv_init_struct2 - for that). - */ -static int __devinit ivtv_init_struct1(struct ivtv *itv) -{ - struct sched_param param = { .sched_priority = 99 }; - - itv->base_addr = pci_resource_start(itv->pdev, 0); - itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */ - itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */ - - mutex_init(&itv->serialize_lock); - mutex_init(&itv->i2c_bus_lock); - mutex_init(&itv->udma.lock); - - spin_lock_init(&itv->lock); - spin_lock_init(&itv->dma_reg_lock); - - init_kthread_worker(&itv->irq_worker); - itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker, - itv->v4l2_dev.name); - if (IS_ERR(itv->irq_worker_task)) { - IVTV_ERR("Could not create ivtv task\n"); - return -1; - } - /* must use the FIFO scheduler as it is realtime sensitive */ - sched_setscheduler(itv->irq_worker_task, SCHED_FIFO, ¶m); - - init_kthread_work(&itv->irq_work, ivtv_irq_work_handler); - - /* Initial settings */ - itv->cxhdl.port = CX2341X_PORT_MEMORY; - itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI; - init_waitqueue_head(&itv->eos_waitq); - init_waitqueue_head(&itv->event_waitq); - init_waitqueue_head(&itv->vsync_waitq); - init_waitqueue_head(&itv->dma_waitq); - init_timer(&itv->dma_timer); - itv->dma_timer.function = ivtv_unfinished_dma; - itv->dma_timer.data = (unsigned long)itv; - - itv->cur_dma_stream = -1; - itv->cur_pio_stream = -1; - - /* Ctrls */ - itv->speed = 1000; - - /* VBI */ - itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; - itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced; - - /* Init the sg table for osd/yuv output */ - sg_init_table(itv->udma.SGlist, IVTV_DMA_SG_OSD_ENT); - - /* OSD */ - itv->osd_global_alpha_state = 1; - itv->osd_global_alpha = 255; - - /* YUV */ - atomic_set(&itv->yuv_info.next_dma_frame, -1); - itv->yuv_info.lace_mode = ivtv_yuv_mode; - itv->yuv_info.lace_threshold = ivtv_yuv_threshold; - itv->yuv_info.max_frames_buffered = 3; - itv->yuv_info.track_osd = 1; - return 0; -} - -/* Second initialization part. Here the card type has been - autodetected. */ -static void __devinit ivtv_init_struct2(struct ivtv *itv) -{ - int i; - - for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++) - if (itv->card->video_inputs[i].video_type == 0) - break; - itv->nof_inputs = i; - for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++) - if (itv->card->audio_inputs[i].audio_type == 0) - break; - itv->nof_audio_inputs = i; - - if (itv->card->hw_all & IVTV_HW_CX25840) { - itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */ - } else { - itv->vbi.sliced_size = 64; /* multiple of 16, real size = 52 */ - } - - /* Find tuner input */ - for (i = 0; i < itv->nof_inputs; i++) { - if (itv->card->video_inputs[i].video_type == - IVTV_CARD_INPUT_VID_TUNER) - break; - } - if (i == itv->nof_inputs) - i = 0; - itv->active_input = i; - itv->audio_input = itv->card->video_inputs[i].audio_index; -} - -static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev, - const struct pci_device_id *pci_id) -{ - u16 cmd; - unsigned char pci_latency; - - IVTV_DEBUG_INFO("Enabling pci device\n"); - - if (pci_enable_device(pdev)) { - IVTV_ERR("Can't enable device!\n"); - return -EIO; - } - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - IVTV_ERR("No suitable DMA available.\n"); - return -EIO; - } - if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) { - IVTV_ERR("Cannot request encoder memory region.\n"); - return -EIO; - } - - if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET, - IVTV_REG_SIZE, "ivtv registers")) { - IVTV_ERR("Cannot request register memory region.\n"); - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - return -EIO; - } - - if (itv->has_cx23415 && - !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, - IVTV_DECODER_SIZE, "ivtv decoder")) { - IVTV_ERR("Cannot request decoder memory region.\n"); - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - return -EIO; - } - - /* Check for bus mastering */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (!(cmd & PCI_COMMAND_MASTER)) { - IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n"); - pci_set_master(pdev); - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - if (!(cmd & PCI_COMMAND_MASTER)) { - IVTV_ERR("Bus Mastering is not enabled\n"); - return -ENXIO; - } - } - IVTV_DEBUG_INFO("Bus Mastering Enabled.\n"); - - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); - - if (pci_latency < 64 && ivtv_pci_latency) { - IVTV_INFO("Unreasonably low latency timer, " - "setting to 64 (was %d)\n", pci_latency); - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); - } - /* This config space value relates to DMA latencies. The - default value 0x8080 is too low however and will lead - to DMA errors. 0xffff is the max value which solves - these problems. */ - pci_write_config_dword(pdev, 0x40, 0xffff); - - IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, " - "irq: %d, latency: %d, memory: 0x%llx\n", - pdev->device, pdev->revision, pdev->bus->number, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - pdev->irq, pci_latency, (u64)itv->base_addr); - - return 0; -} - -static void ivtv_load_and_init_modules(struct ivtv *itv) -{ - u32 hw = itv->card->hw_all; - unsigned i; - - /* check which i2c devices are actually found */ - for (i = 0; i < 32; i++) { - u32 device = 1 << i; - - if (!(device & hw)) - continue; - if (device == IVTV_HW_GPIO || device == IVTV_HW_TVEEPROM) { - /* GPIO and TVEEPROM do not use i2c probing */ - itv->hw_flags |= device; - continue; - } - if (ivtv_i2c_register(itv, i) == 0) - itv->hw_flags |= device; - } - - /* probe for legacy IR controllers that aren't in card definitions */ - if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0) - ivtv_i2c_new_ir_legacy(itv); - - if (itv->card->hw_all & IVTV_HW_CX25840) - itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840); - else if (itv->card->hw_all & IVTV_HW_SAA717X) - itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X); - else if (itv->card->hw_all & IVTV_HW_SAA7114) - itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114); - else - itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115); - itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl); - itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer); - - hw = itv->hw_flags; - - if (itv->card->type == IVTV_CARD_CX23416GYC) { - /* Several variations of this card exist, detect which card - type should be used. */ - if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0) - itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS); - else if ((hw & IVTV_HW_UPD64031A) == 0) - itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR); - } - else if (itv->card->type == IVTV_CARD_GV_MVPRX || - itv->card->type == IVTV_CARD_GV_MVPRX2E) { - /* The crystal frequency of GVMVPRX is 24.576MHz */ - v4l2_subdev_call(itv->sd_video, video, s_crystal_freq, - SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC); - } - - if (hw & IVTV_HW_CX25840) { - itv->vbi.raw_decoder_line_size = 1444; - itv->vbi.raw_decoder_sav_odd_field = 0x20; - itv->vbi.raw_decoder_sav_even_field = 0x60; - itv->vbi.sliced_decoder_line_size = 272; - itv->vbi.sliced_decoder_sav_odd_field = 0xB0; - itv->vbi.sliced_decoder_sav_even_field = 0xF0; - } - - if (hw & IVTV_HW_SAA711X) { - struct v4l2_dbg_chip_ident v; - - /* determine the exact saa711x model */ - itv->hw_flags &= ~IVTV_HW_SAA711X; - - v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER; - strlcpy(v.match.name, "saa7115", sizeof(v.match.name)); - ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v); - if (v.ident == V4L2_IDENT_SAA7114) { - itv->hw_flags |= IVTV_HW_SAA7114; - /* VBI is not yet supported by the saa7114 driver. */ - itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE); - } else { - itv->hw_flags |= IVTV_HW_SAA7115; - } - itv->vbi.raw_decoder_line_size = 1443; - itv->vbi.raw_decoder_sav_odd_field = 0x25; - itv->vbi.raw_decoder_sav_even_field = 0x62; - itv->vbi.sliced_decoder_line_size = 51; - itv->vbi.sliced_decoder_sav_odd_field = 0xAB; - itv->vbi.sliced_decoder_sav_even_field = 0xEC; - } - - if (hw & IVTV_HW_SAA717X) { - itv->vbi.raw_decoder_line_size = 1443; - itv->vbi.raw_decoder_sav_odd_field = 0x25; - itv->vbi.raw_decoder_sav_even_field = 0x62; - itv->vbi.sliced_decoder_line_size = 51; - itv->vbi.sliced_decoder_sav_odd_field = 0xAB; - itv->vbi.sliced_decoder_sav_even_field = 0xEC; - } -} - -static int __devinit ivtv_probe(struct pci_dev *pdev, - const struct pci_device_id *pci_id) -{ - int retval = 0; - int vbi_buf_size; - struct ivtv *itv; - - itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC); - if (itv == NULL) - return -ENOMEM; - itv->pdev = pdev; - itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv", - &ivtv_instance); - - retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev); - if (retval) { - kfree(itv); - return retval; - } - IVTV_INFO("Initializing card %d\n", itv->instance); - - ivtv_process_options(itv); - if (itv->options.cardtype == -1) { - retval = -ENODEV; - goto err; - } - if (ivtv_init_struct1(itv)) { - retval = -ENOMEM; - goto err; - } - retval = cx2341x_handler_init(&itv->cxhdl, 50); - if (retval) - goto err; - itv->v4l2_dev.ctrl_handler = &itv->cxhdl.hdl; - itv->cxhdl.ops = &ivtv_cxhdl_ops; - itv->cxhdl.priv = itv; - itv->cxhdl.func = ivtv_api_func; - - IVTV_DEBUG_INFO("base addr: 0x%llx\n", (u64)itv->base_addr); - - /* PCI Device Setup */ - retval = ivtv_setup_pci(itv, pdev, pci_id); - if (retval == -EIO) - goto free_worker; - if (retval == -ENXIO) - goto free_mem; - - /* map io memory */ - IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", - (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE); - itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET, - IVTV_ENCODER_SIZE); - if (!itv->enc_mem) { - IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " - "encoder memory\n"); - IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of " - "vmalloc address space for this window\n"); - IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); - IVTV_ERR("Use the vmalloc= kernel command line option to set " - "VmallocTotal to a larger value\n"); - retval = -ENOMEM; - goto free_mem; - } - - if (itv->has_cx23415) { - IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", - (u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET, - IVTV_DECODER_SIZE); - if (!itv->dec_mem) { - IVTV_ERR("ioremap failed. Can't get a window into " - "CX23415 decoder memory\n"); - IVTV_ERR("Each capture card with a CX23415 needs 8 MB " - "of vmalloc address space for this window\n"); - IVTV_ERR("Check the output of 'grep Vmalloc " - "/proc/meminfo'\n"); - IVTV_ERR("Use the vmalloc= kernel command line option " - "to set VmallocTotal to a larger value\n"); - retval = -ENOMEM; - goto free_mem; - } - } - else { - itv->dec_mem = itv->enc_mem; - } - - /* map registers memory */ - IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n", - (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - itv->reg_mem = - ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - if (!itv->reg_mem) { - IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 " - "register space\n"); - IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of " - "vmalloc address space for this window\n"); - IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n"); - IVTV_ERR("Use the vmalloc= kernel command line option to set " - "VmallocTotal to a larger value\n"); - retval = -ENOMEM; - goto free_io; - } - - retval = ivtv_gpio_init(itv); - if (retval) - goto free_io; - - /* active i2c */ - IVTV_DEBUG_INFO("activating i2c...\n"); - if (init_ivtv_i2c(itv)) { - IVTV_ERR("Could not initialize i2c\n"); - goto free_io; - } - - if (itv->card->hw_all & IVTV_HW_TVEEPROM) { - /* Based on the model number the cardtype may be changed. - The PCI IDs are not always reliable. */ - ivtv_process_eeprom(itv); - } - if (itv->card->comment) - IVTV_INFO("%s", itv->card->comment); - if (itv->card->v4l2_capabilities == 0) { - /* card was detected but is not supported */ - retval = -ENODEV; - goto free_i2c; - } - - if (itv->std == 0) { - itv->std = V4L2_STD_NTSC_M; - } - - if (itv->options.tuner == -1) { - int i; - - for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) { - if ((itv->std & itv->card->tuners[i].std) == 0) - continue; - itv->options.tuner = itv->card->tuners[i].tuner; - break; - } - } - /* if no tuner was found, then pick the first tuner in the card list */ - if (itv->options.tuner == -1 && itv->card->tuners[0].std) { - itv->std = itv->card->tuners[0].std; - if (itv->std & V4L2_STD_PAL) - itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H; - else if (itv->std & V4L2_STD_NTSC) - itv->std = V4L2_STD_NTSC_M; - else if (itv->std & V4L2_STD_SECAM) - itv->std = V4L2_STD_SECAM_L; - itv->options.tuner = itv->card->tuners[0].tuner; - } - if (itv->options.radio == -1) - itv->options.radio = (itv->card->radio_input.audio_type != 0); - - /* The card is now fully identified, continue with card-specific - initialization. */ - ivtv_init_struct2(itv); - - ivtv_load_and_init_modules(itv); - - if (itv->std & V4L2_STD_525_60) { - itv->is_60hz = 1; - itv->is_out_60hz = 1; - } else { - itv->is_50hz = 1; - itv->is_out_50hz = 1; - } - - itv->yuv_info.osd_full_w = 720; - itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480; - itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w; - itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h; - - cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz); - - itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000; - itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200; - itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000; - itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000; - itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000; - - /* Setup VBI Raw Size. Should be big enough to hold PAL. - It is possible to switch between PAL and NTSC, so we need to - take the largest size here. */ - /* 1456 is multiple of 16, real size = 1444 */ - itv->vbi.raw_size = 1456; - /* We use a buffer size of 1/2 of the total size needed for a - frame. This is actually very useful, since we now receive - a field at a time and that makes 'compressing' the raw data - down to size by stripping off the SAV codes a lot easier. - Note: having two different buffer sizes prevents standard - switching on the fly. We need to find a better solution... */ - vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2; - itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size; - itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36; - - if (itv->options.radio > 0) - itv->v4l2_cap |= V4L2_CAP_RADIO; - - if (itv->options.tuner > -1) { - struct tuner_setup setup; - - setup.addr = ADDR_UNSET; - setup.type = itv->options.tuner; - setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */ - if (itv->options.radio > 0) - setup.mode_mask |= T_RADIO; - setup.tuner_callback = (setup.type == TUNER_XC2028) ? - ivtv_reset_tuner_gpio : NULL; - ivtv_call_all(itv, tuner, s_type_addr, &setup); - if (setup.type == TUNER_XC2028) { - static struct xc2028_ctrl ctrl = { - .fname = XC2028_DEFAULT_FIRMWARE, - .max_len = 64, - }; - struct v4l2_priv_tun_config cfg = { - .tuner = itv->options.tuner, - .priv = &ctrl, - }; - ivtv_call_all(itv, tuner, s_config, &cfg); - } - } - - /* The tuner is fixed to the standard. The other inputs (e.g. S-Video) - are not. */ - itv->tuner_std = itv->std; - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler; - - itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, - V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 0, 0); - itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops, - V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0, 0, 0); - /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported, - mask that menu item. */ - itv->ctrl_audio_playback = - v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, - V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK, - V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, - 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, - V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO); - itv->ctrl_audio_multilingual_playback = - v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops, - V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK, - V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO, - 1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO, - V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); - if (hdl->error) { - retval = hdl->error; - goto free_i2c; - } - v4l2_ctrl_cluster(2, &itv->ctrl_pts); - v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback); - ivtv_call_all(itv, video, s_std_output, itv->std); - /* Turn off the output signal. The mpeg decoder is not yet - active so without this you would get a green image until the - mpeg decoder becomes active. */ - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); - } - - /* clear interrupt mask, effectively disabling interrupts */ - ivtv_set_irq_mask(itv, 0xffffffff); - - /* Register IRQ */ - retval = request_irq(itv->pdev->irq, ivtv_irq_handler, - IRQF_SHARED | IRQF_DISABLED, itv->v4l2_dev.name, (void *)itv); - if (retval) { - IVTV_ERR("Failed to register irq %d\n", retval); - goto free_i2c; - } - - retval = ivtv_streams_setup(itv); - if (retval) { - IVTV_ERR("Error %d setting up streams\n", retval); - goto free_irq; - } - retval = ivtv_streams_register(itv); - if (retval) { - IVTV_ERR("Error %d registering devices\n", retval); - goto free_streams; - } - IVTV_INFO("Initialized card: %s\n", itv->card_name); - return 0; - -free_streams: - ivtv_streams_cleanup(itv, 1); -free_irq: - free_irq(itv->pdev->irq, (void *)itv); -free_i2c: - v4l2_ctrl_handler_free(&itv->cxhdl.hdl); - exit_ivtv_i2c(itv); -free_io: - ivtv_iounmap(itv); -free_mem: - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - if (itv->has_cx23415) - release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); -free_worker: - kthread_stop(itv->irq_worker_task); -err: - if (retval == 0) - retval = -ENODEV; - IVTV_ERR("Error %d on initialization\n", retval); - - v4l2_device_unregister(&itv->v4l2_dev); - kfree(itv); - return retval; -} - -int ivtv_init_on_first_open(struct ivtv *itv) -{ - struct v4l2_frequency vf; - /* Needed to call ioctls later */ - struct ivtv_open_id fh; - int fw_retry_count = 3; - int video_input; - - fh.itv = itv; - - if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) - return -ENXIO; - - if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags)) - return 0; - - while (--fw_retry_count > 0) { - /* load firmware */ - if (ivtv_firmware_init(itv) == 0) - break; - if (fw_retry_count > 1) - IVTV_WARN("Retry loading firmware\n"); - } - - if (fw_retry_count == 0) { - set_bit(IVTV_F_I_FAILED, &itv->i_flags); - return -ENXIO; - } - - /* Try and get firmware versions */ - IVTV_DEBUG_INFO("Getting firmware version..\n"); - ivtv_firmware_versions(itv); - - if (itv->card->hw_all & IVTV_HW_CX25840) - v4l2_subdev_call(itv->sd_video, core, load_fw); - - vf.tuner = 0; - vf.type = V4L2_TUNER_ANALOG_TV; - vf.frequency = 6400; /* the tuner 'baseline' frequency */ - - /* Set initial frequency. For PAL/SECAM broadcasts no - 'default' channel exists AFAIK. */ - if (itv->std == V4L2_STD_NTSC_M_JP) { - vf.frequency = 1460; /* ch. 1 91250*16/1000 */ - } - else if (itv->std & V4L2_STD_NTSC_M) { - vf.frequency = 1076; /* ch. 4 67250*16/1000 */ - } - - video_input = itv->active_input; - itv->active_input++; /* Force update of input */ - ivtv_s_input(NULL, &fh, video_input); - - /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code - in one place. */ - itv->std++; /* Force full standard initialization */ - itv->std_out = itv->std; - ivtv_s_frequency(NULL, &fh, &vf); - - if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { - /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes - the mpeg decoder so now the saa7127 receives a proper - signal. */ - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); - ivtv_init_mpeg_decoder(itv); - } - - /* On a cx23416 this seems to be able to enable DMA to the chip? */ - if (!itv->has_cx23415) - write_reg_sync(0x03, IVTV_REG_DMACONTROL); - - ivtv_s_std_enc(itv, &itv->tuner_std); - - /* Default interrupts enabled. For the PVR350 this includes the - decoder VSYNC interrupt, which is always on. It is not only used - during decoding but also by the OSD. - Some old PVR250 cards had a cx23415, so testing for that is too - general. Instead test if the card has video output capability. */ - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC); - ivtv_set_osd_alpha(itv); - ivtv_s_std_dec(itv, &itv->tuner_std); - } else { - ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT); - } - - /* Setup initial controls */ - cx2341x_handler_setup(&itv->cxhdl); - return 0; -} - -static void ivtv_remove(struct pci_dev *pdev) -{ - struct v4l2_device *v4l2_dev = dev_get_drvdata(&pdev->dev); - struct ivtv *itv = to_ivtv(v4l2_dev); - int i; - - IVTV_DEBUG_INFO("Removing card\n"); - - if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) { - /* Stop all captures */ - IVTV_DEBUG_INFO("Stopping all streams\n"); - if (atomic_read(&itv->capturing) > 0) - ivtv_stop_all_captures(itv); - - /* Stop all decoding */ - IVTV_DEBUG_INFO("Stopping decoding\n"); - - /* Turn off the TV-out */ - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); - if (atomic_read(&itv->decoding) > 0) { - int type; - - if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) - type = IVTV_DEC_STREAM_TYPE_YUV; - else - type = IVTV_DEC_STREAM_TYPE_MPG; - ivtv_stop_v4l2_decode_stream(&itv->streams[type], - V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); - } - ivtv_halt_firmware(itv); - } - - /* Interrupts */ - ivtv_set_irq_mask(itv, 0xffffffff); - del_timer_sync(&itv->dma_timer); - - /* Kill irq worker */ - flush_kthread_worker(&itv->irq_worker); - kthread_stop(itv->irq_worker_task); - - ivtv_streams_cleanup(itv, 1); - ivtv_udma_free(itv); - - v4l2_ctrl_handler_free(&itv->cxhdl.hdl); - - exit_ivtv_i2c(itv); - - free_irq(itv->pdev->irq, (void *)itv); - ivtv_iounmap(itv); - - release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); - release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); - if (itv->has_cx23415) - release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE); - - pci_disable_device(itv->pdev); - for (i = 0; i < IVTV_VBI_FRAMES; i++) - kfree(itv->vbi.sliced_mpeg_data[i]); - - printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name); - - v4l2_device_unregister(&itv->v4l2_dev); - kfree(itv); -} - -/* define a pci_driver for card detection */ -static struct pci_driver ivtv_pci_driver = { - .name = "ivtv", - .id_table = ivtv_pci_tbl, - .probe = ivtv_probe, - .remove = ivtv_remove, -}; - -static int __init module_start(void) -{ - printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION); - - /* Validate parameters */ - if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) { - printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n", - IVTV_MAX_CARDS - 1); - return -1; - } - - if (ivtv_debug < 0 || ivtv_debug > 2047) { - ivtv_debug = 0; - printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n"); - } - - if (pci_register_driver(&ivtv_pci_driver)) { - printk(KERN_ERR "ivtv: Error detecting PCI card\n"); - return -ENODEV; - } - printk(KERN_INFO "ivtv: End initialization\n"); - return 0; -} - -static void __exit module_cleanup(void) -{ - pci_unregister_driver(&ivtv_pci_driver); -} - -/* Note: These symbols are exported because they are used by the ivtvfb - framebuffer module and an infrared module for the IR-blaster. */ -EXPORT_SYMBOL(ivtv_set_irq_mask); -EXPORT_SYMBOL(ivtv_api); -EXPORT_SYMBOL(ivtv_vapi); -EXPORT_SYMBOL(ivtv_vapi_result); -EXPORT_SYMBOL(ivtv_clear_irq_mask); -EXPORT_SYMBOL(ivtv_debug); -#ifdef CONFIG_VIDEO_ADV_DEBUG -EXPORT_SYMBOL(ivtv_fw_debug); -#endif -EXPORT_SYMBOL(ivtv_reset_ir_gpio); -EXPORT_SYMBOL(ivtv_udma_setup); -EXPORT_SYMBOL(ivtv_udma_unmap); -EXPORT_SYMBOL(ivtv_udma_alloc); -EXPORT_SYMBOL(ivtv_udma_prepare); -EXPORT_SYMBOL(ivtv_init_on_first_open); -EXPORT_SYMBOL(ivtv_firmware_check); - -module_init(module_start); -module_exit(module_cleanup); diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h deleted file mode 100644 index a7e00f8938f8..000000000000 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ /dev/null @@ -1,839 +0,0 @@ -/* - ivtv driver internal defines and structures - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_DRIVER_H -#define IVTV_DRIVER_H - -/* Internal header for ivtv project: - * Driver for the cx23415/6 chip. - * Author: Kevin Thayer (nufan_wfk at yahoo.com) - * License: GPL - * http://www.ivtvdriver.org - * - * ----- - * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> - * and Takeru KOMORIYA<komoriya@paken.org> - * - * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> - * using information provided by Jiun-Kuei Jung @ AVerMedia. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/list.h> -#include <linux/unistd.h> -#include <linux/pagemap.h> -#include <linux/scatterlist.h> -#include <linux/kthread.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <asm/uaccess.h> -#include <asm/byteorder.h> - -#include <linux/dvb/video.h> -#include <linux/dvb/audio.h> -#include <media/v4l2-common.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-device.h> -#include <media/v4l2-fh.h> -#include <media/tuner.h> -#include <media/cx2341x.h> -#include <media/ir-kbd-i2c.h> - -#include <linux/ivtv.h> - -/* Memory layout */ -#define IVTV_ENCODER_OFFSET 0x00000000 -#define IVTV_ENCODER_SIZE 0x00800000 /* Total size is 0x01000000, but only first half is used */ -#define IVTV_DECODER_OFFSET 0x01000000 -#define IVTV_DECODER_SIZE 0x00800000 /* Total size is 0x01000000, but only first half is used */ -#define IVTV_REG_OFFSET 0x02000000 -#define IVTV_REG_SIZE 0x00010000 - -/* Maximum ivtv driver instances. Some people have a huge number of - capture cards, so set this to a high value. */ -#define IVTV_MAX_CARDS 32 - -#define IVTV_ENC_STREAM_TYPE_MPG 0 -#define IVTV_ENC_STREAM_TYPE_YUV 1 -#define IVTV_ENC_STREAM_TYPE_VBI 2 -#define IVTV_ENC_STREAM_TYPE_PCM 3 -#define IVTV_ENC_STREAM_TYPE_RAD 4 -#define IVTV_DEC_STREAM_TYPE_MPG 5 -#define IVTV_DEC_STREAM_TYPE_VBI 6 -#define IVTV_DEC_STREAM_TYPE_VOUT 7 -#define IVTV_DEC_STREAM_TYPE_YUV 8 -#define IVTV_MAX_STREAMS 9 - -#define IVTV_DMA_SG_OSD_ENT (2883584/PAGE_SIZE) /* sg entities */ - -/* DMA Registers */ -#define IVTV_REG_DMAXFER (0x0000) -#define IVTV_REG_DMASTATUS (0x0004) -#define IVTV_REG_DECDMAADDR (0x0008) -#define IVTV_REG_ENCDMAADDR (0x000c) -#define IVTV_REG_DMACONTROL (0x0010) -#define IVTV_REG_IRQSTATUS (0x0040) -#define IVTV_REG_IRQMASK (0x0048) - -/* Setup Registers */ -#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8) -#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC) -#define IVTV_REG_DEC_SDRAM_REFRESH (0x08F8) -#define IVTV_REG_DEC_SDRAM_PRECHARGE (0x08FC) -#define IVTV_REG_VDM (0x2800) -#define IVTV_REG_AO (0x2D00) -#define IVTV_REG_BYTEFLUSH (0x2D24) -#define IVTV_REG_SPU (0x9050) -#define IVTV_REG_HW_BLOCKS (0x9054) -#define IVTV_REG_VPU (0x9058) -#define IVTV_REG_APU (0xA064) - -/* Other registers */ -#define IVTV_REG_DEC_LINE_FIELD (0x28C0) - -/* debugging */ -extern int ivtv_debug; -#ifdef CONFIG_VIDEO_ADV_DEBUG -extern int ivtv_fw_debug; -#endif - -#define IVTV_DBGFLG_WARN (1 << 0) -#define IVTV_DBGFLG_INFO (1 << 1) -#define IVTV_DBGFLG_MB (1 << 2) -#define IVTV_DBGFLG_IOCTL (1 << 3) -#define IVTV_DBGFLG_FILE (1 << 4) -#define IVTV_DBGFLG_DMA (1 << 5) -#define IVTV_DBGFLG_IRQ (1 << 6) -#define IVTV_DBGFLG_DEC (1 << 7) -#define IVTV_DBGFLG_YUV (1 << 8) -#define IVTV_DBGFLG_I2C (1 << 9) -/* Flag to turn on high volume debugging */ -#define IVTV_DBGFLG_HIGHVOL (1 << 10) - -#define IVTV_DEBUG(x, type, fmt, args...) \ - do { \ - if ((x) & ivtv_debug) \ - v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args); \ - } while (0) -#define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args) -#define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) -#define IVTV_DEBUG_MB(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_MB, "mb", fmt , ## args) -#define IVTV_DEBUG_DMA(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DMA, "dma", fmt , ## args) -#define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) -#define IVTV_DEBUG_FILE(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_FILE, "file", fmt , ## args) -#define IVTV_DEBUG_I2C(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) -#define IVTV_DEBUG_IRQ(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) -#define IVTV_DEBUG_DEC(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_DEC, "dec", fmt , ## args) -#define IVTV_DEBUG_YUV(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) - -#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ - do { \ - if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ - v4l2_info(&itv->v4l2_dev, " " type ": " fmt , ##args); \ - } while (0) -#define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args) -#define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args) -#define IVTV_DEBUG_HI_MB(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_MB, "mb", fmt , ## args) -#define IVTV_DEBUG_HI_DMA(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA, "dma", fmt , ## args) -#define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args) -#define IVTV_DEBUG_HI_FILE(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_FILE, "file", fmt , ## args) -#define IVTV_DEBUG_HI_I2C(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C, "i2c", fmt , ## args) -#define IVTV_DEBUG_HI_IRQ(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ, "irq", fmt , ## args) -#define IVTV_DEBUG_HI_DEC(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC, "dec", fmt , ## args) -#define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) - -/* Standard kernel messages */ -#define IVTV_ERR(fmt, args...) v4l2_err(&itv->v4l2_dev, fmt , ## args) -#define IVTV_WARN(fmt, args...) v4l2_warn(&itv->v4l2_dev, fmt , ## args) -#define IVTV_INFO(fmt, args...) v4l2_info(&itv->v4l2_dev, fmt , ## args) - -/* output modes (cx23415 only) */ -#define OUT_NONE 0 -#define OUT_MPG 1 -#define OUT_YUV 2 -#define OUT_UDMA_YUV 3 -#define OUT_PASSTHROUGH 4 - -#define IVTV_MAX_PGM_INDEX (400) - -/* Default I2C SCL period in microseconds */ -#define IVTV_DEFAULT_I2C_CLOCK_PERIOD 20 - -struct ivtv_options { - int kilobytes[IVTV_MAX_STREAMS]; /* size in kilobytes of each stream */ - int cardtype; /* force card type on load */ - int tuner; /* set tuner on load */ - int radio; /* enable/disable radio */ - int newi2c; /* new I2C algorithm */ - int i2c_clock_period; /* period of SCL for I2C bus */ -}; - -/* ivtv-specific mailbox template */ -struct ivtv_mailbox { - u32 flags; - u32 cmd; - u32 retval; - u32 timeout; - u32 data[CX2341X_MBOX_MAX_DATA]; -}; - -struct ivtv_api_cache { - unsigned long last_jiffies; /* when last command was issued */ - u32 data[CX2341X_MBOX_MAX_DATA]; /* last sent api data */ -}; - -struct ivtv_mailbox_data { - volatile struct ivtv_mailbox __iomem *mbox; - /* Bits 0-2 are for the encoder mailboxes, 0-1 are for the decoder mailboxes. - If the bit is set, then the corresponding mailbox is in use by the driver. */ - unsigned long busy; - u8 max_mbox; -}; - -/* per-buffer bit flags */ -#define IVTV_F_B_NEED_BUF_SWAP (1 << 0) /* this buffer should be byte swapped */ - -/* per-stream, s_flags */ -#define IVTV_F_S_DMA_PENDING 0 /* this stream has pending DMA */ -#define IVTV_F_S_DMA_HAS_VBI 1 /* the current DMA request also requests VBI data */ -#define IVTV_F_S_NEEDS_DATA 2 /* this decoding stream needs more data */ - -#define IVTV_F_S_CLAIMED 3 /* this stream is claimed */ -#define IVTV_F_S_STREAMING 4 /* the fw is decoding/encoding this stream */ -#define IVTV_F_S_INTERNAL_USE 5 /* this stream is used internally (sliced VBI processing) */ -#define IVTV_F_S_PASSTHROUGH 6 /* this stream is in passthrough mode */ -#define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */ -#define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ - -#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */ -#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */ - -/* per-ivtv, i_flags */ -#define IVTV_F_I_DMA 0 /* DMA in progress */ -#define IVTV_F_I_UDMA 1 /* UDMA in progress */ -#define IVTV_F_I_UDMA_PENDING 2 /* UDMA pending */ -#define IVTV_F_I_SPEED_CHANGE 3 /* a speed change is in progress */ -#define IVTV_F_I_EOS 4 /* end of encoder stream reached */ -#define IVTV_F_I_RADIO_USER 5 /* the radio tuner is selected */ -#define IVTV_F_I_DIG_RST 6 /* reset digitizer */ -#define IVTV_F_I_DEC_YUV 7 /* YUV instead of MPG is being decoded */ -#define IVTV_F_I_UPDATE_CC 9 /* CC should be updated */ -#define IVTV_F_I_UPDATE_WSS 10 /* WSS should be updated */ -#define IVTV_F_I_UPDATE_VPS 11 /* VPS should be updated */ -#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ -#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ -#define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ -#define IVTV_F_I_HAVE_WORK 15 /* used in the interrupt handler: there is work to be done */ -#define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */ -#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ -#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ -#define IVTV_F_I_PIO 19 /* PIO in progress */ -#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ -#define IVTV_F_I_INITED 21 /* set after first open */ -#define IVTV_F_I_FAILED 22 /* set if first open failed */ - -/* Event notifications */ -#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ -#define IVTV_F_I_EV_VSYNC 29 /* VSYNC event */ -#define IVTV_F_I_EV_VSYNC_FIELD 30 /* VSYNC event field (0 = first, 1 = second field) */ -#define IVTV_F_I_EV_VSYNC_ENABLED 31 /* VSYNC event enabled */ - -/* Scatter-Gather array element, used in DMA transfers */ -struct ivtv_sg_element { - __le32 src; - __le32 dst; - __le32 size; -}; - -struct ivtv_sg_host_element { - u32 src; - u32 dst; - u32 size; -}; - -struct ivtv_user_dma { - struct mutex lock; - int page_count; - struct page *map[IVTV_DMA_SG_OSD_ENT]; - /* Needed when dealing with highmem userspace buffers */ - struct page *bouncemap[IVTV_DMA_SG_OSD_ENT]; - - /* Base Dev SG Array for cx23415/6 */ - struct ivtv_sg_element SGarray[IVTV_DMA_SG_OSD_ENT]; - dma_addr_t SG_handle; - int SG_length; - - /* SG List of Buffers */ - struct scatterlist SGlist[IVTV_DMA_SG_OSD_ENT]; -}; - -struct ivtv_dma_page_info { - unsigned long uaddr; - unsigned long first; - unsigned long last; - unsigned int offset; - unsigned int tail; - int page_count; -}; - -struct ivtv_buffer { - struct list_head list; - dma_addr_t dma_handle; - unsigned short b_flags; - unsigned short dma_xfer_cnt; - char *buf; - u32 bytesused; - u32 readpos; -}; - -struct ivtv_queue { - struct list_head list; /* the list of buffers in this queue */ - u32 buffers; /* number of buffers in this queue */ - u32 length; /* total number of bytes of available buffer space */ - u32 bytesused; /* total number of bytes used in this queue */ -}; - -struct ivtv; /* forward reference */ - -struct ivtv_stream { - /* These first four fields are always set, even if the stream - is not actually created. */ - struct video_device *vdev; /* NULL when stream not created */ - struct ivtv *itv; /* for ease of use */ - const char *name; /* name of the stream */ - int type; /* stream type */ - u32 caps; /* V4L2 capabilities */ - - struct v4l2_fh *fh; /* pointer to the streaming filehandle */ - spinlock_t qlock; /* locks access to the queues */ - unsigned long s_flags; /* status flags, see above */ - int dma; /* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */ - u32 pending_offset; - u32 pending_backup; - u64 pending_pts; - - u32 dma_offset; - u32 dma_backup; - u64 dma_pts; - - int subtype; - wait_queue_head_t waitq; - u32 dma_last_offset; - - /* Buffer Stats */ - u32 buffers; - u32 buf_size; - u32 buffers_stolen; - - /* Buffer Queues */ - struct ivtv_queue q_free; /* free buffers */ - struct ivtv_queue q_full; /* full buffers */ - struct ivtv_queue q_io; /* waiting for I/O */ - struct ivtv_queue q_dma; /* waiting for DMA */ - struct ivtv_queue q_predma; /* waiting for DMA */ - - /* DMA xfer counter, buffers belonging to the same DMA - xfer will have the same dma_xfer_cnt. */ - u16 dma_xfer_cnt; - - /* Base Dev SG Array for cx23415/6 */ - struct ivtv_sg_host_element *sg_pending; - struct ivtv_sg_host_element *sg_processing; - struct ivtv_sg_element *sg_dma; - dma_addr_t sg_handle; - int sg_pending_size; - int sg_processing_size; - int sg_processed; - - /* SG List of Buffers */ - struct scatterlist *SGlist; -}; - -struct ivtv_open_id { - struct v4l2_fh fh; - int type; /* stream type */ - int yuv_frames; /* 1: started OUT_UDMA_YUV output mode */ - struct ivtv *itv; -}; - -static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh) -{ - return container_of(fh, struct ivtv_open_id, fh); -} - -struct yuv_frame_info -{ - u32 update; - s32 src_x; - s32 src_y; - u32 src_w; - u32 src_h; - s32 dst_x; - s32 dst_y; - u32 dst_w; - u32 dst_h; - s32 pan_x; - s32 pan_y; - u32 vis_w; - u32 vis_h; - u32 interlaced_y; - u32 interlaced_uv; - s32 tru_x; - u32 tru_w; - u32 tru_h; - u32 offset_y; - s32 lace_mode; - u32 sync_field; - u32 delay; - u32 interlaced; -}; - -#define IVTV_YUV_MODE_INTERLACED 0x00 -#define IVTV_YUV_MODE_PROGRESSIVE 0x01 -#define IVTV_YUV_MODE_AUTO 0x02 -#define IVTV_YUV_MODE_MASK 0x03 - -#define IVTV_YUV_SYNC_EVEN 0x00 -#define IVTV_YUV_SYNC_ODD 0x04 -#define IVTV_YUV_SYNC_MASK 0x04 - -#define IVTV_YUV_BUFFERS 8 - -struct yuv_playback_info -{ - u32 reg_2834; - u32 reg_2838; - u32 reg_283c; - u32 reg_2840; - u32 reg_2844; - u32 reg_2848; - u32 reg_2854; - u32 reg_285c; - u32 reg_2864; - - u32 reg_2870; - u32 reg_2874; - u32 reg_2890; - u32 reg_2898; - u32 reg_289c; - - u32 reg_2918; - u32 reg_291c; - u32 reg_2920; - u32 reg_2924; - u32 reg_2928; - u32 reg_292c; - u32 reg_2930; - - u32 reg_2934; - - u32 reg_2938; - u32 reg_293c; - u32 reg_2940; - u32 reg_2944; - u32 reg_2948; - u32 reg_294c; - u32 reg_2950; - u32 reg_2954; - u32 reg_2958; - u32 reg_295c; - u32 reg_2960; - u32 reg_2964; - u32 reg_2968; - u32 reg_296c; - - u32 reg_2970; - - int v_filter_1; - int v_filter_2; - int h_filter; - - u8 track_osd; /* Should yuv output track the OSD size & position */ - - u32 osd_x_offset; - u32 osd_y_offset; - - u32 osd_x_pan; - u32 osd_y_pan; - - u32 osd_vis_w; - u32 osd_vis_h; - - u32 osd_full_w; - u32 osd_full_h; - - int decode_height; - - int lace_mode; - int lace_threshold; - int lace_sync_field; - - atomic_t next_dma_frame; - atomic_t next_fill_frame; - - u32 yuv_forced_update; - int update_frame; - - u8 fields_lapsed; /* Counter used when delaying a frame */ - - struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS]; - struct yuv_frame_info old_frame_info; - struct yuv_frame_info old_frame_info_args; - - void *blanking_ptr; - dma_addr_t blanking_dmaptr; - - int stream_size; - - u8 draw_frame; /* PVR350 buffer to draw into */ - u8 max_frames_buffered; /* Maximum number of frames to buffer */ - - struct v4l2_rect main_rect; - u32 v4l2_src_w; - u32 v4l2_src_h; - - u8 running; /* Have any frames been displayed */ -}; - -#define IVTV_VBI_FRAMES 32 - -/* VBI data */ -struct vbi_cc { - u8 odd[2]; /* two-byte payload of odd field */ - u8 even[2]; /* two-byte payload of even field */; -}; - -struct vbi_vps { - u8 data[5]; /* five-byte VPS payload */ -}; - -struct vbi_info { - /* VBI general data, does not change during streaming */ - - u32 raw_decoder_line_size; /* raw VBI line size from digitizer */ - u8 raw_decoder_sav_odd_field; /* raw VBI Start Active Video digitizer code of odd field */ - u8 raw_decoder_sav_even_field; /* raw VBI Start Active Video digitizer code of even field */ - u32 sliced_decoder_line_size; /* sliced VBI line size from digitizer */ - u8 sliced_decoder_sav_odd_field; /* sliced VBI Start Active Video digitizer code of odd field */ - u8 sliced_decoder_sav_even_field; /* sliced VBI Start Active Video digitizer code of even field */ - - u32 start[2]; /* start of first VBI line in the odd/even fields */ - u32 count; /* number of VBI lines per field */ - u32 raw_size; /* size of raw VBI line from the digitizer */ - u32 sliced_size; /* size of sliced VBI line from the digitizer */ - - u32 dec_start; /* start in decoder memory of VBI re-insertion buffers */ - u32 enc_start; /* start in encoder memory of VBI capture buffers */ - u32 enc_size; /* size of VBI capture area */ - int fpi; /* number of VBI frames per interrupt */ - - struct v4l2_format in; /* current VBI capture format */ - struct v4l2_sliced_vbi_format *sliced_in; /* convenience pointer to sliced struct in vbi.in union */ - int insert_mpeg; /* if non-zero, then embed VBI data in MPEG stream */ - - /* Raw VBI compatibility hack */ - - u32 frame; /* frame counter hack needed for backwards compatibility - of old VBI software */ - - /* Sliced VBI output data */ - - struct vbi_cc cc_payload[256]; /* sliced VBI CC payload array: it is an array to - prevent dropping CC data if they couldn't be - processed fast enough */ - int cc_payload_idx; /* index in cc_payload */ - u8 cc_missing_cnt; /* counts number of frames without CC for passthrough mode */ - int wss_payload; /* sliced VBI WSS payload */ - u8 wss_missing_cnt; /* counts number of frames without WSS for passthrough mode */ - struct vbi_vps vps_payload; /* sliced VBI VPS payload */ - - /* Sliced VBI capture data */ - - struct v4l2_sliced_vbi_data sliced_data[36]; /* sliced VBI storage for VBI encoder stream */ - struct v4l2_sliced_vbi_data sliced_dec_data[36];/* sliced VBI storage for VBI decoder stream */ - - /* VBI Embedding data */ - - /* Buffer for VBI data inserted into MPEG stream. - The first byte is a dummy byte that's never used. - The next 16 bytes contain the MPEG header for the VBI data, - the remainder is the actual VBI data. - The max size accepted by the MPEG VBI reinsertion turns out - to be 1552 bytes, which happens to be 4 + (1 + 42) * (2 * 18) bytes, - where 4 is a four byte header, 42 is the max sliced VBI payload, 1 is - a single line header byte and 2 * 18 is the number of VBI lines per frame. - - However, it seems that the data must be 1K aligned, so we have to - pad the data until the 1 or 2 K boundary. - - This pointer array will allocate 2049 bytes to store each VBI frame. */ - u8 *sliced_mpeg_data[IVTV_VBI_FRAMES]; - u32 sliced_mpeg_size[IVTV_VBI_FRAMES]; - struct ivtv_buffer sliced_mpeg_buf; /* temporary buffer holding data from sliced_mpeg_data */ - u32 inserted_frame; /* index in sliced_mpeg_size of next sliced data - to be inserted in the MPEG stream */ -}; - -/* forward declaration of struct defined in ivtv-cards.h */ -struct ivtv_card; - -/* Struct to hold info about ivtv cards */ -struct ivtv { - /* General fixed card data */ - struct pci_dev *pdev; /* PCI device */ - const struct ivtv_card *card; /* card information */ - const char *card_name; /* full name of the card */ - const struct ivtv_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */ - u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */ - u8 pvr150_workaround; /* 1 if the cx25840 needs to workaround a PVR150 bug */ - u8 nof_inputs; /* number of video inputs */ - u8 nof_audio_inputs; /* number of audio inputs */ - u32 v4l2_cap; /* V4L2 capabilities of card */ - u32 hw_flags; /* hardware description of the board */ - v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */ - struct v4l2_subdev *sd_video; /* controlling video decoder subdev */ - struct v4l2_subdev *sd_audio; /* controlling audio subdev */ - struct v4l2_subdev *sd_muxer; /* controlling audio muxer subdev */ - resource_size_t base_addr; /* PCI resource base address */ - volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */ - volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */ - volatile void __iomem *reg_mem; /* pointer to mapped registers */ - struct ivtv_options options; /* user options */ - - struct v4l2_device v4l2_dev; - struct cx2341x_handler cxhdl; - struct { - /* PTS/Frame count control cluster */ - struct v4l2_ctrl *ctrl_pts; - struct v4l2_ctrl *ctrl_frame; - }; - struct { - /* Audio Playback control cluster */ - struct v4l2_ctrl *ctrl_audio_playback; - struct v4l2_ctrl *ctrl_audio_multilingual_playback; - }; - struct v4l2_ctrl_handler hdl_gpio; - struct v4l2_subdev sd_gpio; /* GPIO sub-device */ - u16 instance; - - /* High-level state info */ - unsigned long i_flags; /* global ivtv flags */ - u8 is_50hz; /* 1 if the current capture standard is 50 Hz */ - u8 is_60hz /* 1 if the current capture standard is 60 Hz */; - u8 is_out_50hz /* 1 if the current TV output standard is 50 Hz */; - u8 is_out_60hz /* 1 if the current TV output standard is 60 Hz */; - int output_mode; /* decoder output mode: NONE, MPG, YUV, UDMA YUV, passthrough */ - u32 audio_input; /* current audio input */ - u32 active_input; /* current video input */ - u32 active_output; /* current video output */ - v4l2_std_id std; /* current capture TV standard */ - v4l2_std_id std_out; /* current TV output standard */ - u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */ - u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */ - - /* Locking */ - spinlock_t lock; /* lock access to this struct */ - struct mutex serialize_lock; /* mutex used to serialize open/close/start/stop/ioctl operations */ - - /* Streams */ - int stream_buf_size[IVTV_MAX_STREAMS]; /* stream buffer size */ - struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* stream data */ - atomic_t capturing; /* count number of active capture streams */ - atomic_t decoding; /* count number of active decoding streams */ - - - /* Interrupts & DMA */ - u32 irqmask; /* active interrupts */ - u32 irq_rr_idx; /* round-robin stream index */ - struct kthread_worker irq_worker; /* kthread worker for PIO/YUV/VBI actions */ - struct task_struct *irq_worker_task; /* task for irq_worker */ - struct kthread_work irq_work; /* kthread work entry */ - spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ - int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */ - int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */ - u32 dma_data_req_offset; /* store offset in decoder memory of current DMA request */ - u32 dma_data_req_size; /* store size of current DMA request */ - int dma_retries; /* current DMA retry attempt */ - struct ivtv_user_dma udma; /* user based DMA for OSD */ - struct timer_list dma_timer; /* timer used to catch unfinished DMAs */ - u32 last_vsync_field; /* last seen vsync field */ - wait_queue_head_t dma_waitq; /* wake up when the current DMA is finished */ - wait_queue_head_t eos_waitq; /* wake up when EOS arrives */ - wait_queue_head_t event_waitq; /* wake up when the next decoder event arrives */ - wait_queue_head_t vsync_waitq; /* wake up when the next decoder vsync arrives */ - - - /* Mailbox */ - struct ivtv_mailbox_data enc_mbox; /* encoder mailboxes */ - struct ivtv_mailbox_data dec_mbox; /* decoder mailboxes */ - struct ivtv_api_cache api_cache[256]; /* cached API commands */ - - - /* I2C */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - int i2c_state; /* i2c bit state */ - struct mutex i2c_bus_lock; /* lock i2c bus */ - - struct IR_i2c_init_data ir_i2c_init_data; - - /* Program Index information */ - u32 pgm_info_offset; /* start of pgm info in encoder memory */ - u32 pgm_info_num; /* number of elements in the pgm cyclic buffer in encoder memory */ - u32 pgm_info_write_idx; /* last index written by the card that was transferred to pgm_info[] */ - u32 pgm_info_read_idx; /* last index in pgm_info read by the application */ - struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; /* filled from the pgm cyclic buffer on the card */ - - - /* Miscellaneous */ - u32 open_id; /* incremented each time an open occurs, is >= 1 */ - int search_pack_header; /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */ - int speed; /* current playback speed setting */ - u8 speed_mute_audio; /* 1 if audio should be muted when fast forward */ - u64 mpg_data_received; /* number of bytes received from the MPEG stream */ - u64 vbi_data_inserted; /* number of VBI bytes inserted into the MPEG stream */ - u32 last_dec_timing[3]; /* cache last retrieved pts/scr/frame values */ - unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */ - u32 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */ - - - /* VBI state info */ - struct vbi_info vbi; /* VBI-specific data */ - - - /* YUV playback */ - struct yuv_playback_info yuv_info; /* YUV playback data */ - - - /* OSD support */ - unsigned long osd_video_pbase; - int osd_global_alpha_state; /* 1 = global alpha is on */ - int osd_local_alpha_state; /* 1 = local alpha is on */ - int osd_chroma_key_state; /* 1 = chroma-keying is on */ - u8 osd_global_alpha; /* current global alpha */ - u32 osd_chroma_key; /* current chroma key */ - struct v4l2_rect osd_rect; /* current OSD position and size */ - struct v4l2_rect main_rect; /* current Main window position and size */ - struct osd_info *osd_info; /* ivtvfb private OSD info */ - void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */ -}; - -static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev) -{ - return container_of(v4l2_dev, struct ivtv, v4l2_dev); -} - -/* Globals */ -extern int ivtv_first_minor; - -/*==============Prototypes==================*/ - -/* Hardware/IRQ */ -void ivtv_set_irq_mask(struct ivtv *itv, u32 mask); -void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask); - -/* try to set output mode, return current mode. */ -int ivtv_set_output_mode(struct ivtv *itv, int mode); - -/* return current output stream based on current mode */ -struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv); - -/* Return non-zero if a signal is pending */ -int ivtv_msleep_timeout(unsigned int msecs, int intr); - -/* Wait on queue, returns -EINTR if interrupted */ -int ivtv_waitq(wait_queue_head_t *waitq); - -/* Read Hauppauge eeprom */ -struct tveeprom; /* forward reference */ -void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); - -/* First-open initialization: load firmware, init cx25840, etc. */ -int ivtv_init_on_first_open(struct ivtv *itv); - -/* Test if the current VBI mode is raw (1) or sliced (0) */ -static inline int ivtv_raw_vbi(const struct ivtv *itv) -{ - return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE; -} - -/* This is a PCI post thing, where if the pci register is not read, then - the write doesn't always take effect right away. By reading back the - register any pending PCI writes will be performed (in order), and so - you can be sure that the writes are guaranteed to be done. - - Rarely needed, only in some timing sensitive cases. - Apparently if this is not done some motherboards seem - to kill the firmware and get into the broken state until computer is - rebooted. */ -#define write_sync(val, reg) \ - do { writel(val, reg); readl(reg); } while (0) - -#define read_reg(reg) readl(itv->reg_mem + (reg)) -#define write_reg(val, reg) writel(val, itv->reg_mem + (reg)) -#define write_reg_sync(val, reg) \ - do { write_reg(val, reg); read_reg(reg); } while (0) - -#define read_enc(addr) readl(itv->enc_mem + (u32)(addr)) -#define write_enc(val, addr) writel(val, itv->enc_mem + (u32)(addr)) -#define write_enc_sync(val, addr) \ - do { write_enc(val, addr); read_enc(addr); } while (0) - -#define read_dec(addr) readl(itv->dec_mem + (u32)(addr)) -#define write_dec(val, addr) writel(val, itv->dec_mem + (u32)(addr)) -#define write_dec_sync(val, addr) \ - do { write_dec(val, addr); read_dec(addr); } while (0) - -/* Call the specified callback for all subdevs matching hw (if 0, then - match them all). Ignore any errors. */ -#define ivtv_call_hw(itv, hw, o, f, args...) \ - do { \ - struct v4l2_subdev *__sd; \ - __v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd, \ - !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \ - } while (0) - -#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args) - -/* Call the specified callback for all subdevs matching hw (if 0, then - match them all). If the callback returns an error other than 0 or - -ENOIOCTLCMD, then return with that error code. */ -#define ivtv_call_hw_err(itv, hw, o, f, args...) \ -({ \ - struct v4l2_subdev *__sd; \ - __v4l2_device_call_subdevs_until_err_p(&(itv)->v4l2_dev, __sd, \ - !(hw) || (__sd->grp_id & (hw)), o, f , ##args); \ -}) - -#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args) - -#endif diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c deleted file mode 100644 index 88bce907cdef..000000000000 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ /dev/null @@ -1,1070 +0,0 @@ -/* - file operation functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-fileops.h" -#include "ivtv-i2c.h" -#include "ivtv-queue.h" -#include "ivtv-udma.h" -#include "ivtv-irq.h" -#include "ivtv-vbi.h" -#include "ivtv-mailbox.h" -#include "ivtv-routing.h" -#include "ivtv-streams.h" -#include "ivtv-yuv.h" -#include "ivtv-ioctl.h" -#include "ivtv-cards.h" -#include "ivtv-firmware.h" -#include <media/v4l2-event.h> -#include <media/saa7115.h> - -/* This function tries to claim the stream for a specific file descriptor. - If no one else is using this stream then the stream is claimed and - associated VBI streams are also automatically claimed. - Possible error returns: -EBUSY if someone else has claimed - the stream or 0 on success. */ -static int ivtv_claim_stream(struct ivtv_open_id *id, int type) -{ - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[type]; - struct ivtv_stream *s_vbi; - int vbi_type; - - if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { - /* someone already claimed this stream */ - if (s->fh == &id->fh) { - /* yes, this file descriptor did. So that's OK. */ - return 0; - } - if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI || - type == IVTV_ENC_STREAM_TYPE_VBI)) { - /* VBI is handled already internally, now also assign - the file descriptor to this stream for external - reading of the stream. */ - s->fh = &id->fh; - IVTV_DEBUG_INFO("Start Read VBI\n"); - return 0; - } - /* someone else is using this stream already */ - IVTV_DEBUG_INFO("Stream %d is busy\n", type); - return -EBUSY; - } - s->fh = &id->fh; - if (type == IVTV_DEC_STREAM_TYPE_VBI) { - /* Enable reinsertion interrupt */ - ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); - } - - /* IVTV_DEC_STREAM_TYPE_MPG needs to claim IVTV_DEC_STREAM_TYPE_VBI, - IVTV_ENC_STREAM_TYPE_MPG needs to claim IVTV_ENC_STREAM_TYPE_VBI - (provided VBI insertion is on and sliced VBI is selected), for all - other streams we're done */ - if (type == IVTV_DEC_STREAM_TYPE_MPG) { - vbi_type = IVTV_DEC_STREAM_TYPE_VBI; - } else if (type == IVTV_ENC_STREAM_TYPE_MPG && - itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) { - vbi_type = IVTV_ENC_STREAM_TYPE_VBI; - } else { - return 0; - } - s_vbi = &itv->streams[vbi_type]; - - if (!test_and_set_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags)) { - /* Enable reinsertion interrupt */ - if (vbi_type == IVTV_DEC_STREAM_TYPE_VBI) - ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); - } - /* mark that it is used internally */ - set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags); - return 0; -} - -/* This function releases a previously claimed stream. It will take into - account associated VBI streams. */ -void ivtv_release_stream(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - struct ivtv_stream *s_vbi; - - s->fh = NULL; - if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) && - test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { - /* this stream is still in use internally */ - return; - } - if (!test_and_clear_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { - IVTV_DEBUG_WARN("Release stream %s not in use!\n", s->name); - return; - } - - ivtv_flush_queues(s); - - /* disable reinsertion interrupt */ - if (s->type == IVTV_DEC_STREAM_TYPE_VBI) - ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); - - /* IVTV_DEC_STREAM_TYPE_MPG needs to release IVTV_DEC_STREAM_TYPE_VBI, - IVTV_ENC_STREAM_TYPE_MPG needs to release IVTV_ENC_STREAM_TYPE_VBI, - for all other streams we're done */ - if (s->type == IVTV_DEC_STREAM_TYPE_MPG) - s_vbi = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; - else if (s->type == IVTV_ENC_STREAM_TYPE_MPG) - s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - else - return; - - /* clear internal use flag */ - if (!test_and_clear_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags)) { - /* was already cleared */ - return; - } - if (s_vbi->fh) { - /* VBI stream still claimed by a file descriptor */ - return; - } - /* disable reinsertion interrupt */ - if (s_vbi->type == IVTV_DEC_STREAM_TYPE_VBI) - ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT); - clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags); - ivtv_flush_queues(s_vbi); -} - -static void ivtv_dualwatch(struct ivtv *itv) -{ - struct v4l2_tuner vt; - u32 new_stereo_mode; - const u32 dual = 0x02; - - new_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode); - memset(&vt, 0, sizeof(vt)); - ivtv_call_all(itv, tuner, g_tuner, &vt); - if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2)) - new_stereo_mode = dual; - - if (new_stereo_mode == itv->dualwatch_stereo_mode) - return; - - IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n", - itv->dualwatch_stereo_mode, new_stereo_mode); - if (v4l2_ctrl_s_ctrl(itv->cxhdl.audio_mode, new_stereo_mode)) - IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n"); -} - -static void ivtv_update_pgm_info(struct ivtv *itv) -{ - u32 wr_idx = (read_enc(itv->pgm_info_offset) - itv->pgm_info_offset - 4) / 24; - int cnt; - int i = 0; - - if (wr_idx >= itv->pgm_info_num) { - IVTV_DEBUG_WARN("Invalid PGM index %d (>= %d)\n", wr_idx, itv->pgm_info_num); - return; - } - cnt = (wr_idx + itv->pgm_info_num - itv->pgm_info_write_idx) % itv->pgm_info_num; - while (i < cnt) { - int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num; - struct v4l2_enc_idx_entry *e = itv->pgm_info + idx; - u32 addr = itv->pgm_info_offset + 4 + idx * 24; - const int mapping[8] = { -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, -1, - V4L2_ENC_IDX_FRAME_B, -1, -1, -1 }; - // 1=I, 2=P, 4=B - - e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32); - if (e->offset > itv->mpg_data_received) { - break; - } - e->offset += itv->vbi_data_inserted; - e->length = read_enc(addr); - e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32); - e->flags = mapping[read_enc(addr + 12) & 7]; - i++; - } - itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num; -} - -static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err) -{ - struct ivtv *itv = s->itv; - struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - struct ivtv_buffer *buf; - DEFINE_WAIT(wait); - - *err = 0; - while (1) { - if (s->type == IVTV_ENC_STREAM_TYPE_MPG) { - /* Process pending program info updates and pending VBI data */ - ivtv_update_pgm_info(itv); - - if (time_after(jiffies, - itv->dualwatch_jiffies + - msecs_to_jiffies(1000))) { - itv->dualwatch_jiffies = jiffies; - ivtv_dualwatch(itv); - } - - if (test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) && - !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) { - while ((buf = ivtv_dequeue(s_vbi, &s_vbi->q_full))) { - /* byteswap and process VBI data */ - ivtv_process_vbi_data(itv, buf, s_vbi->dma_pts, s_vbi->type); - ivtv_enqueue(s_vbi, buf, &s_vbi->q_free); - } - } - buf = &itv->vbi.sliced_mpeg_buf; - if (buf->readpos != buf->bytesused) { - return buf; - } - } - - /* do we have leftover data? */ - buf = ivtv_dequeue(s, &s->q_io); - if (buf) - return buf; - - /* do we have new data? */ - buf = ivtv_dequeue(s, &s->q_full); - if (buf) { - if ((buf->b_flags & IVTV_F_B_NEED_BUF_SWAP) == 0) - return buf; - buf->b_flags &= ~IVTV_F_B_NEED_BUF_SWAP; - if (s->type == IVTV_ENC_STREAM_TYPE_MPG) - /* byteswap MPG data */ - ivtv_buf_swap(buf); - else if (s->type != IVTV_DEC_STREAM_TYPE_VBI) { - /* byteswap and process VBI data */ - ivtv_process_vbi_data(itv, buf, s->dma_pts, s->type); - } - return buf; - } - - /* return if end of stream */ - if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { - IVTV_DEBUG_INFO("EOS %s\n", s->name); - return NULL; - } - - /* return if file was opened with O_NONBLOCK */ - if (non_block) { - *err = -EAGAIN; - return NULL; - } - - /* wait for more data to arrive */ - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); - /* New buffers might have become available before we were added to the waitqueue */ - if (!s->q_full.buffers) - schedule(); - finish_wait(&s->waitq, &wait); - mutex_lock(&itv->serialize_lock); - if (signal_pending(current)) { - /* return if a signal was received */ - IVTV_DEBUG_INFO("User stopped %s\n", s->name); - *err = -EINTR; - return NULL; - } - } -} - -static void ivtv_setup_sliced_vbi_buf(struct ivtv *itv) -{ - int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES; - - itv->vbi.sliced_mpeg_buf.buf = itv->vbi.sliced_mpeg_data[idx]; - itv->vbi.sliced_mpeg_buf.bytesused = itv->vbi.sliced_mpeg_size[idx]; - itv->vbi.sliced_mpeg_buf.readpos = 0; -} - -static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *buf, - char __user *ubuf, size_t ucount) -{ - struct ivtv *itv = s->itv; - size_t len = buf->bytesused - buf->readpos; - - if (len > ucount) len = ucount; - if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG && - !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) { - const char *start = buf->buf + buf->readpos; - const char *p = start + 1; - const u8 *q; - u8 ch = itv->search_pack_header ? 0xba : 0xe0; - int stuffing, i; - - while (start + len > p && (q = memchr(p, 0, start + len - p))) { - p = q + 1; - if ((char *)q + 15 >= buf->buf + buf->bytesused || - q[1] != 0 || q[2] != 1 || q[3] != ch) { - continue; - } - if (!itv->search_pack_header) { - if ((q[6] & 0xc0) != 0x80) - continue; - if (((q[7] & 0xc0) == 0x80 && (q[9] & 0xf0) == 0x20) || - ((q[7] & 0xc0) == 0xc0 && (q[9] & 0xf0) == 0x30)) { - ch = 0xba; - itv->search_pack_header = 1; - p = q + 9; - } - continue; - } - stuffing = q[13] & 7; - /* all stuffing bytes must be 0xff */ - for (i = 0; i < stuffing; i++) - if (q[14 + i] != 0xff) - break; - if (i == stuffing && (q[4] & 0xc4) == 0x44 && (q[12] & 3) == 3 && - q[14 + stuffing] == 0 && q[15 + stuffing] == 0 && - q[16 + stuffing] == 1) { - itv->search_pack_header = 0; - len = (char *)q - start; - ivtv_setup_sliced_vbi_buf(itv); - break; - } - } - } - if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) { - IVTV_DEBUG_WARN("copy %zd bytes to user failed for %s\n", len, s->name); - return -EFAULT; - } - /*IVTV_INFO("copied %lld %d %d %d %d %d vbi %d\n", itv->mpg_data_received, len, ucount, - buf->readpos, buf->bytesused, buf->bytesused - buf->readpos - len, - buf == &itv->vbi.sliced_mpeg_buf); */ - buf->readpos += len; - if (s->type == IVTV_ENC_STREAM_TYPE_MPG && buf != &itv->vbi.sliced_mpeg_buf) - itv->mpg_data_received += len; - return len; -} - -static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_count, int non_block) -{ - struct ivtv *itv = s->itv; - size_t tot_written = 0; - int single_frame = 0; - - if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) { - /* shouldn't happen */ - IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name); - return -EIO; - } - - /* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should - arrive one-by-one, so make sure we never output more than one VBI frame at a time */ - if (s->type == IVTV_DEC_STREAM_TYPE_VBI || - (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv))) - single_frame = 1; - - for (;;) { - struct ivtv_buffer *buf; - int rc; - - buf = ivtv_get_buffer(s, non_block, &rc); - /* if there is no data available... */ - if (buf == NULL) { - /* if we got data, then return that regardless */ - if (tot_written) - break; - /* EOS condition */ - if (rc == 0) { - clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); - ivtv_release_stream(s); - } - /* set errno */ - return rc; - } - rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written); - if (buf != &itv->vbi.sliced_mpeg_buf) { - ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io); - } - else if (buf->readpos == buf->bytesused) { - int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES; - itv->vbi.sliced_mpeg_size[idx] = 0; - itv->vbi.inserted_frame++; - itv->vbi_data_inserted += buf->bytesused; - } - if (rc < 0) - return rc; - tot_written += rc; - - if (tot_written == tot_count || single_frame) - break; - } - return tot_written; -} - -static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t count, - loff_t *pos, int non_block) -{ - ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0; - struct ivtv *itv = s->itv; - - IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc); - if (rc > 0) - pos += rc; - return rc; -} - -int ivtv_start_capture(struct ivtv_open_id *id) -{ - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - struct ivtv_stream *s_vbi; - - if (s->type == IVTV_ENC_STREAM_TYPE_RAD || - s->type == IVTV_DEC_STREAM_TYPE_MPG || - s->type == IVTV_DEC_STREAM_TYPE_YUV || - s->type == IVTV_DEC_STREAM_TYPE_VOUT) { - /* you cannot read from these stream types. */ - return -EPERM; - } - - /* Try to claim this stream. */ - if (ivtv_claim_stream(id, s->type)) - return -EBUSY; - - /* This stream does not need to start capturing */ - if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { - set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - return 0; - } - - /* If capture is already in progress, then we also have to - do nothing extra. */ - if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) { - set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - return 0; - } - - /* Start VBI capture if required */ - s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - if (s->type == IVTV_ENC_STREAM_TYPE_MPG && - test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) && - !test_and_set_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) { - /* Note: the IVTV_ENC_STREAM_TYPE_VBI is claimed - automatically when the MPG stream is claimed. - We only need to start the VBI capturing. */ - if (ivtv_start_v4l2_encode_stream(s_vbi)) { - IVTV_DEBUG_WARN("VBI capture start failed\n"); - - /* Failure, clean up and return an error */ - clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags); - clear_bit(IVTV_F_S_STREAMING, &s->s_flags); - /* also releases the associated VBI stream */ - ivtv_release_stream(s); - return -EIO; - } - IVTV_DEBUG_INFO("VBI insertion started\n"); - } - - /* Tell the card to start capturing */ - if (!ivtv_start_v4l2_encode_stream(s)) { - /* We're done */ - set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - /* Resume a possibly paused encoder */ - if (test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) - ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); - return 0; - } - - /* failure, clean up */ - IVTV_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name); - - /* Note: the IVTV_ENC_STREAM_TYPE_VBI is released - automatically when the MPG stream is released. - We only need to stop the VBI capturing. */ - if (s->type == IVTV_ENC_STREAM_TYPE_MPG && - test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) { - ivtv_stop_v4l2_encode_stream(s_vbi, 0); - clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags); - } - clear_bit(IVTV_F_S_STREAMING, &s->s_flags); - ivtv_release_stream(s); - return -EIO; -} - -ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos) -{ - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - ssize_t rc; - - IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name); - - if (mutex_lock_interruptible(&itv->serialize_lock)) - return -ERESTARTSYS; - rc = ivtv_start_capture(id); - if (!rc) - rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK); - mutex_unlock(&itv->serialize_lock); - return rc; -} - -int ivtv_start_decoding(struct ivtv_open_id *id, int speed) -{ - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - int rc; - - if (atomic_read(&itv->decoding) == 0) { - if (ivtv_claim_stream(id, s->type)) { - /* someone else is using this stream already */ - IVTV_DEBUG_WARN("start decode, stream already claimed\n"); - return -EBUSY; - } - rc = ivtv_start_v4l2_decode_stream(s, 0); - if (rc < 0) { - if (rc == -EAGAIN) - rc = ivtv_start_v4l2_decode_stream(s, 0); - if (rc < 0) - return rc; - } - } - if (s->type == IVTV_DEC_STREAM_TYPE_MPG) - return ivtv_set_speed(itv, speed); - return 0; -} - -static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) -{ - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - struct yuv_playback_info *yi = &itv->yuv_info; - struct ivtv_buffer *buf; - struct ivtv_queue q; - int bytes_written = 0; - int mode; - int rc; - DEFINE_WAIT(wait); - - IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name); - - if (s->type != IVTV_DEC_STREAM_TYPE_MPG && - s->type != IVTV_DEC_STREAM_TYPE_YUV && - s->type != IVTV_DEC_STREAM_TYPE_VOUT) - /* not decoder streams */ - return -EPERM; - - /* Try to claim this stream */ - if (ivtv_claim_stream(id, s->type)) - return -EBUSY; - - /* This stream does not need to start any decoding */ - if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) { - int elems = count / sizeof(struct v4l2_sliced_vbi_data); - - set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - return ivtv_write_vbi_from_user(itv, - (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); - } - - mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV; - - if (ivtv_set_output_mode(itv, mode) != mode) { - ivtv_release_stream(s); - return -EBUSY; - } - ivtv_queue_init(&q); - set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - - /* Start decoder (returns 0 if already started) */ - rc = ivtv_start_decoding(id, itv->speed); - if (rc) { - IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name); - - /* failure, clean up */ - clear_bit(IVTV_F_S_STREAMING, &s->s_flags); - clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); - return rc; - } - -retry: - /* If possible, just DMA the entire frame - Check the data transfer size - since we may get here before the stream has been fully set-up */ - if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) { - while (count >= itv->dma_data_req_size) { - rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf); - - if (rc < 0) - return rc; - - bytes_written += itv->dma_data_req_size; - user_buf += itv->dma_data_req_size; - count -= itv->dma_data_req_size; - } - if (count == 0) { - IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); - return bytes_written; - } - } - - for (;;) { - /* Gather buffers */ - while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io))) - ivtv_enqueue(s, buf, &q); - while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_free))) { - ivtv_enqueue(s, buf, &q); - } - if (q.buffers) - break; - if (filp->f_flags & O_NONBLOCK) - return -EAGAIN; - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE); - /* New buffers might have become free before we were added to the waitqueue */ - if (!s->q_free.buffers) - schedule(); - finish_wait(&s->waitq, &wait); - mutex_lock(&itv->serialize_lock); - if (signal_pending(current)) { - IVTV_DEBUG_INFO("User stopped %s\n", s->name); - return -EINTR; - } - } - - /* copy user data into buffers */ - while ((buf = ivtv_dequeue(s, &q))) { - /* yuv is a pain. Don't copy more data than needed for a single - frame, otherwise we lose sync with the incoming stream */ - if (s->type == IVTV_DEC_STREAM_TYPE_YUV && - yi->stream_size + count > itv->dma_data_req_size) - rc = ivtv_buf_copy_from_user(s, buf, user_buf, - itv->dma_data_req_size - yi->stream_size); - else - rc = ivtv_buf_copy_from_user(s, buf, user_buf, count); - - /* Make sure we really got all the user data */ - if (rc < 0) { - ivtv_queue_move(s, &q, NULL, &s->q_free, 0); - return rc; - } - user_buf += rc; - count -= rc; - bytes_written += rc; - - if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { - yi->stream_size += rc; - /* If we have a complete yuv frame, break loop now */ - if (yi->stream_size == itv->dma_data_req_size) { - ivtv_enqueue(s, buf, &s->q_full); - yi->stream_size = 0; - break; - } - } - - if (buf->bytesused != s->buf_size) { - /* incomplete, leave in q_io for next time */ - ivtv_enqueue(s, buf, &s->q_io); - break; - } - /* Byteswap MPEG buffer */ - if (s->type == IVTV_DEC_STREAM_TYPE_MPG) - ivtv_buf_swap(buf); - ivtv_enqueue(s, buf, &s->q_full); - } - - if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) { - if (s->q_full.length >= itv->dma_data_req_size) { - int got_sig; - - if (mode == OUT_YUV) - ivtv_yuv_setup_stream_frame(itv); - - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - while (!(got_sig = signal_pending(current)) && - test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) { - schedule(); - } - finish_wait(&itv->dma_waitq, &wait); - mutex_lock(&itv->serialize_lock); - if (got_sig) { - IVTV_DEBUG_INFO("User interrupted %s\n", s->name); - return -EINTR; - } - - clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); - ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); - ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 1); - } - } - /* more user data is available, wait until buffers become free - to transfer the rest. */ - if (count && !(filp->f_flags & O_NONBLOCK)) - goto retry; - IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused); - return bytes_written; -} - -ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos) -{ - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - ssize_t res; - - if (mutex_lock_interruptible(&itv->serialize_lock)) - return -ERESTARTSYS; - res = ivtv_write(filp, user_buf, count, pos); - mutex_unlock(&itv->serialize_lock); - return res; -} - -unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait) -{ - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - int res = 0; - - /* add stream's waitq to the poll list */ - IVTV_DEBUG_HI_FILE("Decoder poll\n"); - - /* If there are subscribed events, then only use the new event - API instead of the old video.h based API. */ - if (!list_empty(&id->fh.subscribed)) { - poll_wait(filp, &id->fh.wait, wait); - /* Turn off the old-style vsync events */ - clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); - if (v4l2_event_pending(&id->fh)) - res = POLLPRI; - } else { - /* This is the old-style API which is here only for backwards - compatibility. */ - poll_wait(filp, &s->waitq, wait); - set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); - if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) || - test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) - res = POLLPRI; - } - - /* Allow write if buffers are available for writing */ - if (s->q_free.buffers) - res |= POLLOUT | POLLWRNORM; - return res; -} - -unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait) -{ - unsigned long req_events = poll_requested_events(wait); - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - unsigned res = 0; - - /* Start a capture if there is none */ - if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) && - (req_events & (POLLIN | POLLRDNORM))) { - int rc; - - mutex_lock(&itv->serialize_lock); - rc = ivtv_start_capture(id); - mutex_unlock(&itv->serialize_lock); - if (rc) { - IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n", - s->name, rc); - return POLLERR; - } - IVTV_DEBUG_FILE("Encoder poll started capture\n"); - } - - /* add stream's waitq to the poll list */ - IVTV_DEBUG_HI_FILE("Encoder poll\n"); - poll_wait(filp, &s->waitq, wait); - if (v4l2_event_pending(&id->fh)) - res |= POLLPRI; - else - poll_wait(filp, &id->fh.wait, wait); - - if (s->q_full.length || s->q_io.length) - return res | POLLIN | POLLRDNORM; - if (eof) - return res | POLLHUP; - return res; -} - -void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end) -{ - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - - IVTV_DEBUG_FILE("close() of %s\n", s->name); - - /* 'Unclaim' this stream */ - - /* Stop capturing */ - if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { - struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - - IVTV_DEBUG_INFO("close stopping capture\n"); - /* Special case: a running VBI capture for VBI insertion - in the mpeg stream. Need to stop that too. */ - if (id->type == IVTV_ENC_STREAM_TYPE_MPG && - test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags) && - !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) { - IVTV_DEBUG_INFO("close stopping embedded VBI capture\n"); - ivtv_stop_v4l2_encode_stream(s_vbi, 0); - } - if ((id->type == IVTV_DEC_STREAM_TYPE_VBI || - id->type == IVTV_ENC_STREAM_TYPE_VBI) && - test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) { - /* Also used internally, don't stop capturing */ - s->fh = NULL; - } - else { - ivtv_stop_v4l2_encode_stream(s, gop_end); - } - } - if (!gop_end) { - clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); - clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - ivtv_release_stream(s); - } -} - -static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) -{ - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - - IVTV_DEBUG_FILE("close() of %s\n", s->name); - - if (id->type == IVTV_DEC_STREAM_TYPE_YUV && - test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) { - /* Restore registers we've changed & clean up any mess */ - ivtv_yuv_close(itv); - } - - /* Stop decoding */ - if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { - IVTV_DEBUG_INFO("close stopping decode\n"); - - ivtv_stop_v4l2_decode_stream(s, flags, pts); - itv->output_mode = OUT_NONE; - } - clear_bit(IVTV_F_S_APPL_IO, &s->s_flags); - clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - - if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames) - itv->output_mode = OUT_NONE; - - itv->speed = 0; - clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); - ivtv_release_stream(s); -} - -int ivtv_v4l2_close(struct file *filp) -{ - struct v4l2_fh *fh = filp->private_data; - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - - IVTV_DEBUG_FILE("close %s\n", s->name); - - mutex_lock(&itv->serialize_lock); - - /* Stop radio */ - if (id->type == IVTV_ENC_STREAM_TYPE_RAD && - v4l2_fh_is_singular_file(filp)) { - /* Closing radio device, return to TV mode */ - ivtv_mute(itv); - /* Mark that the radio is no longer in use */ - clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); - /* Switch tuner to TV */ - ivtv_call_all(itv, core, s_std, itv->std); - /* Select correct audio input (i.e. TV tuner or Line in) */ - ivtv_audio_set_io(itv); - if (itv->hw_flags & IVTV_HW_SAA711X) { - ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, - SAA7115_FREQ_32_11_MHZ, 0); - } - if (atomic_read(&itv->capturing) > 0) { - /* Undo video mute */ - ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, - v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) | - (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8)); - } - /* Done! Unmute and continue. */ - ivtv_unmute(itv); - } - - v4l2_fh_del(fh); - v4l2_fh_exit(fh); - - /* Easy case first: this stream was never claimed by us */ - if (s->fh != &id->fh) - goto close_done; - - /* 'Unclaim' this stream */ - - if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { - struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; - - ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0); - - /* If all output streams are closed, and if the user doesn't have - IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */ - if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { - /* disable CC on TV-out */ - ivtv_disable_cc(itv); - } - } else { - ivtv_stop_capture(id, 0); - } -close_done: - kfree(id); - mutex_unlock(&itv->serialize_lock); - return 0; -} - -static int ivtv_open(struct file *filp) -{ - struct video_device *vdev = video_devdata(filp); - struct ivtv_stream *s = video_get_drvdata(vdev); - struct ivtv *itv = s->itv; - struct ivtv_open_id *item; - int res = 0; - - IVTV_DEBUG_FILE("open %s\n", s->name); - - if (ivtv_init_on_first_open(itv)) { - IVTV_ERR("Failed to initialize on device %s\n", - video_device_node_name(vdev)); - return -ENXIO; - } - -#ifdef CONFIG_VIDEO_ADV_DEBUG - /* Unless ivtv_fw_debug is set, error out if firmware dead. */ - if (ivtv_fw_debug) { - IVTV_WARN("Opening %s with dead firmware lockout disabled\n", - video_device_node_name(vdev)); - IVTV_WARN("Selected firmware errors will be ignored\n"); - } else { -#else - if (1) { -#endif - res = ivtv_firmware_check(itv, "ivtv_serialized_open"); - if (res == -EAGAIN) - res = ivtv_firmware_check(itv, "ivtv_serialized_open"); - if (res < 0) - return -EIO; - } - - if (s->type == IVTV_DEC_STREAM_TYPE_MPG && - test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) - return -EBUSY; - - if (s->type == IVTV_DEC_STREAM_TYPE_YUV && - test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags)) - return -EBUSY; - - if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { - if (read_reg(0x82c) == 0) { - IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n"); - /* return -ENODEV; */ - } - ivtv_udma_alloc(itv); - } - - /* Allocate memory */ - item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL); - if (NULL == item) { - IVTV_DEBUG_WARN("nomem on v4l2 open\n"); - return -ENOMEM; - } - v4l2_fh_init(&item->fh, s->vdev); - item->itv = itv; - item->type = s->type; - - filp->private_data = &item->fh; - v4l2_fh_add(&item->fh); - - if (item->type == IVTV_ENC_STREAM_TYPE_RAD && - v4l2_fh_is_singular_file(filp)) { - if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { - if (atomic_read(&itv->capturing) > 0) { - /* switching to radio while capture is - in progress is not polite */ - v4l2_fh_del(&item->fh); - v4l2_fh_exit(&item->fh); - kfree(item); - return -EBUSY; - } - } - /* Mark that the radio is being used. */ - set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); - /* We have the radio */ - ivtv_mute(itv); - /* Switch tuner to radio */ - ivtv_call_all(itv, tuner, s_radio); - /* Select the correct audio input (i.e. radio tuner) */ - ivtv_audio_set_io(itv); - if (itv->hw_flags & IVTV_HW_SAA711X) { - ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, - SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL); - } - /* Done! Unmute and continue. */ - ivtv_unmute(itv); - } - - /* YUV or MPG Decoding Mode? */ - if (s->type == IVTV_DEC_STREAM_TYPE_MPG) { - clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); - } else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) { - set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags); - /* For yuv, we need to know the dma size before we start */ - itv->dma_data_req_size = - 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); - itv->yuv_info.stream_size = 0; - } - return 0; -} - -int ivtv_v4l2_open(struct file *filp) -{ - struct video_device *vdev = video_devdata(filp); - int res; - - if (mutex_lock_interruptible(vdev->lock)) - return -ERESTARTSYS; - res = ivtv_open(filp); - mutex_unlock(vdev->lock); - return res; -} - -void ivtv_mute(struct ivtv *itv) -{ - if (atomic_read(&itv->capturing)) - ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1); - IVTV_DEBUG_INFO("Mute\n"); -} - -void ivtv_unmute(struct ivtv *itv) -{ - if (atomic_read(&itv->capturing)) { - ivtv_msleep_timeout(100, 0); - ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); - ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0); - } - IVTV_DEBUG_INFO("Unmute\n"); -} diff --git a/drivers/media/video/ivtv/ivtv-fileops.h b/drivers/media/video/ivtv/ivtv-fileops.h deleted file mode 100644 index 049a2923965d..000000000000 --- a/drivers/media/video/ivtv/ivtv-fileops.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - file operation functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_FILEOPS_H -#define IVTV_FILEOPS_H - -/* Testing/Debugging */ -int ivtv_v4l2_open(struct file *filp); -ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count, - loff_t * pos); -ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count, - loff_t * pos); -int ivtv_v4l2_close(struct file *filp); -unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait); -unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait); -int ivtv_start_capture(struct ivtv_open_id *id); -void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end); -int ivtv_start_decoding(struct ivtv_open_id *id, int speed); -void ivtv_mute(struct ivtv *itv); -void ivtv_unmute(struct ivtv *itv); - -/* Utilities */ - -/* Release a previously claimed stream. */ -void ivtv_release_stream(struct ivtv_stream *s); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c deleted file mode 100644 index 6ec7705af555..000000000000 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - ivtv firmware functions. - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-mailbox.h" -#include "ivtv-firmware.h" -#include "ivtv-yuv.h" -#include "ivtv-ioctl.h" -#include "ivtv-cards.h" -#include <linux/firmware.h> -#include <media/saa7127.h> - -#define IVTV_MASK_SPU_ENABLE 0xFFFFFFFE -#define IVTV_MASK_VPU_ENABLE15 0xFFFFFFF6 -#define IVTV_MASK_VPU_ENABLE16 0xFFFFFFFB -#define IVTV_CMD_VDM_STOP 0x00000000 -#define IVTV_CMD_AO_STOP 0x00000005 -#define IVTV_CMD_APU_PING 0x00000000 -#define IVTV_CMD_VPU_STOP15 0xFFFFFFFE -#define IVTV_CMD_VPU_STOP16 0xFFFFFFEE -#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF -#define IVTV_CMD_SPU_STOP 0x00000001 -#define IVTV_CMD_SDRAM_PRECHARGE_INIT 0x0000001A -#define IVTV_CMD_SDRAM_REFRESH_INIT 0x80000640 -#define IVTV_SDRAM_SLEEPTIME 600 - -#define IVTV_DECODE_INIT_MPEG_FILENAME "v4l-cx2341x-init.mpg" -#define IVTV_DECODE_INIT_MPEG_SIZE (152*1024) - -/* Encoder/decoder firmware sizes */ -#define IVTV_FW_ENC_SIZE (376836) -#define IVTV_FW_DEC_SIZE (256*1024) - -static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size) -{ - const struct firmware *fw = NULL; - int retries = 3; - -retry: - if (retries && request_firmware(&fw, fn, &itv->pdev->dev) == 0) { - int i; - volatile u32 __iomem *dst = (volatile u32 __iomem *)mem; - const u32 *src = (const u32 *)fw->data; - - if (fw->size != size) { - /* Due to race conditions in firmware loading (esp. with udev <0.95) - the wrong file was sometimes loaded. So we check filesizes to - see if at least the right-sized file was loaded. If not, then we - retry. */ - IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size); - release_firmware(fw); - retries--; - goto retry; - } - for (i = 0; i < fw->size; i += 4) { - /* no need for endianness conversion on the ppc */ - __raw_writel(*src, dst); - dst++; - src++; - } - IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size); - release_firmware(fw); - return size; - } - IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); - IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n"); - return -ENOMEM; -} - -void ivtv_halt_firmware(struct ivtv *itv) -{ - IVTV_DEBUG_INFO("Preparing for firmware halt.\n"); - if (itv->has_cx23415 && itv->dec_mbox.mbox) - ivtv_vapi(itv, CX2341X_DEC_HALT_FW, 0); - if (itv->enc_mbox.mbox) - ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0); - - ivtv_msleep_timeout(10, 0); - itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL; - - IVTV_DEBUG_INFO("Stopping VDM\n"); - write_reg(IVTV_CMD_VDM_STOP, IVTV_REG_VDM); - - IVTV_DEBUG_INFO("Stopping AO\n"); - write_reg(IVTV_CMD_AO_STOP, IVTV_REG_AO); - - IVTV_DEBUG_INFO("pinging (?) APU\n"); - write_reg(IVTV_CMD_APU_PING, IVTV_REG_APU); - - IVTV_DEBUG_INFO("Stopping VPU\n"); - if (!itv->has_cx23415) - write_reg(IVTV_CMD_VPU_STOP16, IVTV_REG_VPU); - else - write_reg(IVTV_CMD_VPU_STOP15, IVTV_REG_VPU); - - IVTV_DEBUG_INFO("Resetting Hw Blocks\n"); - write_reg(IVTV_CMD_HW_BLOCKS_RST, IVTV_REG_HW_BLOCKS); - - IVTV_DEBUG_INFO("Stopping SPU\n"); - write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU); - - ivtv_msleep_timeout(10, 0); - - IVTV_DEBUG_INFO("init Encoder SDRAM pre-charge\n"); - write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_ENC_SDRAM_PRECHARGE); - - IVTV_DEBUG_INFO("init Encoder SDRAM refresh to 1us\n"); - write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_ENC_SDRAM_REFRESH); - - if (itv->has_cx23415) { - IVTV_DEBUG_INFO("init Decoder SDRAM pre-charge\n"); - write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_DEC_SDRAM_PRECHARGE); - - IVTV_DEBUG_INFO("init Decoder SDRAM refresh to 1us\n"); - write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH); - } - - IVTV_DEBUG_INFO("Sleeping for %dms\n", IVTV_SDRAM_SLEEPTIME); - ivtv_msleep_timeout(IVTV_SDRAM_SLEEPTIME, 0); -} - -void ivtv_firmware_versions(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - - /* Encoder */ - ivtv_vapi_result(itv, data, CX2341X_ENC_GET_VERSION, 0); - IVTV_INFO("Encoder revision: 0x%08x\n", data[0]); - - if (data[0] != 0x02060039) - IVTV_WARN("Recommended firmware version is 0x02060039.\n"); - - if (itv->has_cx23415) { - /* Decoder */ - ivtv_vapi_result(itv, data, CX2341X_DEC_GET_VERSION, 0); - IVTV_INFO("Decoder revision: 0x%08x\n", data[0]); - } -} - -static int ivtv_firmware_copy(struct ivtv *itv) -{ - IVTV_DEBUG_INFO("Loading encoder image\n"); - if (load_fw_direct(CX2341X_FIRM_ENC_FILENAME, - itv->enc_mem, itv, IVTV_FW_ENC_SIZE) != IVTV_FW_ENC_SIZE) { - IVTV_DEBUG_WARN("failed loading encoder firmware\n"); - return -3; - } - if (!itv->has_cx23415) - return 0; - - IVTV_DEBUG_INFO("Loading decoder image\n"); - if (load_fw_direct(CX2341X_FIRM_DEC_FILENAME, - itv->dec_mem, itv, IVTV_FW_DEC_SIZE) != IVTV_FW_DEC_SIZE) { - IVTV_DEBUG_WARN("failed loading decoder firmware\n"); - return -1; - } - return 0; -} - -static volatile struct ivtv_mailbox __iomem *ivtv_search_mailbox(const volatile u8 __iomem *mem, u32 size) -{ - int i; - - /* mailbox is preceded by a 16 byte 'magic cookie' starting at a 256-byte - address boundary */ - for (i = 0; i < size; i += 0x100) { - if (readl(mem + i) == 0x12345678 && - readl(mem + i + 4) == 0x34567812 && - readl(mem + i + 8) == 0x56781234 && - readl(mem + i + 12) == 0x78123456) { - return (volatile struct ivtv_mailbox __iomem *)(mem + i + 16); - } - } - return NULL; -} - -int ivtv_firmware_init(struct ivtv *itv) -{ - int err; - - ivtv_halt_firmware(itv); - - /* load firmware */ - err = ivtv_firmware_copy(itv); - if (err) { - IVTV_DEBUG_WARN("Error %d loading firmware\n", err); - return err; - } - - /* start firmware */ - write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU); - ivtv_msleep_timeout(100, 0); - if (itv->has_cx23415) - write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE15, IVTV_REG_VPU); - else - write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE16, IVTV_REG_VPU); - ivtv_msleep_timeout(100, 0); - - /* find mailboxes and ping firmware */ - itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE); - if (itv->enc_mbox.mbox == NULL) - IVTV_ERR("Encoder mailbox not found\n"); - else if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0)) { - IVTV_ERR("Encoder firmware dead!\n"); - itv->enc_mbox.mbox = NULL; - } - if (itv->enc_mbox.mbox == NULL) - return -ENODEV; - - if (!itv->has_cx23415) - return 0; - - itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE); - if (itv->dec_mbox.mbox == NULL) { - IVTV_ERR("Decoder mailbox not found\n"); - } else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) { - IVTV_ERR("Decoder firmware dead!\n"); - itv->dec_mbox.mbox = NULL; - } else { - /* Firmware okay, so check yuv output filter table */ - ivtv_yuv_filter_check(itv); - } - return itv->dec_mbox.mbox ? 0 : -ENODEV; -} - -void ivtv_init_mpeg_decoder(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - long readbytes; - volatile u8 __iomem *mem_offset; - - data[0] = 0; - data[1] = itv->cxhdl.width; /* YUV source width */ - data[2] = itv->cxhdl.height; - data[3] = itv->cxhdl.audio_properties; /* Audio settings to use, - bitmap. see docs. */ - if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) { - IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n"); - return; - } - - if (ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1) != 0) { - IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n"); - return; - } - ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data); - mem_offset = itv->dec_mem + data[1]; - - if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME, - mem_offset, itv, IVTV_DECODE_INIT_MPEG_SIZE)) <= 0) { - IVTV_DEBUG_WARN("failed to read mpeg decoder initialisation file %s\n", - IVTV_DECODE_INIT_MPEG_FILENAME); - } else { - ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0); - ivtv_msleep_timeout(100, 0); - } - ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1); -} - -/* Try to restart the card & restore previous settings */ -int ivtv_firmware_restart(struct ivtv *itv) -{ - int rc = 0; - v4l2_std_id std; - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) - /* Display test image during restart */ - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, - SAA7127_INPUT_TYPE_TEST_IMAGE, - itv->card->video_outputs[itv->active_output].video_output, - 0); - - mutex_lock(&itv->udma.lock); - - rc = ivtv_firmware_init(itv); - if (rc) { - mutex_unlock(&itv->udma.lock); - return rc; - } - - /* Allow settings to reload */ - ivtv_mailbox_cache_invalidate(itv); - - /* Restore encoder video standard */ - std = itv->std; - itv->std = 0; - ivtv_s_std_enc(itv, &std); - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - ivtv_init_mpeg_decoder(itv); - - /* Restore decoder video standard */ - std = itv->std_out; - itv->std_out = 0; - ivtv_s_std_dec(itv, &std); - - /* Restore framebuffer if active */ - if (itv->ivtvfb_restore) - itv->ivtvfb_restore(itv); - - /* Restore alpha settings */ - ivtv_set_osd_alpha(itv); - - /* Restore normal output */ - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, - SAA7127_INPUT_TYPE_NORMAL, - itv->card->video_outputs[itv->active_output].video_output, - 0); - } - - mutex_unlock(&itv->udma.lock); - return rc; -} - -/* Check firmware running state. The checks fall through - allowing multiple failures to be logged. */ -int ivtv_firmware_check(struct ivtv *itv, char *where) -{ - int res = 0; - - /* Check encoder is still running */ - if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) { - IVTV_WARN("Encoder has died : %s\n", where); - res = -1; - } - - /* Also check audio. Only check if not in use & encoder is okay */ - if (!res && !atomic_read(&itv->capturing) && - (!atomic_read(&itv->decoding) || - (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV, - &itv->i_flags)))) { - - if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) { - IVTV_WARN("Audio has died (Encoder OK) : %s\n", where); - res = -2; - } - } - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - /* Second audio check. Skip if audio already failed */ - if (res != -2 && read_dec(0x100) != read_dec(0x104)) { - /* Wait & try again to be certain. */ - ivtv_msleep_timeout(14, 0); - if (read_dec(0x100) != read_dec(0x104)) { - IVTV_WARN("Audio has died (Decoder) : %s\n", - where); - res = -1; - } - } - - /* Check decoder is still running */ - if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) { - IVTV_WARN("Decoder has died : %s\n", where); - res = -1; - } - } - - /* If something failed & currently idle, try to reload */ - if (res && !atomic_read(&itv->capturing) && - !atomic_read(&itv->decoding)) { - IVTV_INFO("Detected in %s that firmware had failed - " - "Reloading\n", where); - res = ivtv_firmware_restart(itv); - /* - * Even if restarted ok, still signal a problem had occurred. - * The caller can come through this function again to check - * if things are really ok after the restart. - */ - if (!res) { - IVTV_INFO("Firmware restart okay\n"); - res = -EAGAIN; - } else { - IVTV_INFO("Firmware restart failed\n"); - } - } else if (res) { - res = -EIO; - } - - return res; -} - -MODULE_FIRMWARE(CX2341X_FIRM_ENC_FILENAME); -MODULE_FIRMWARE(CX2341X_FIRM_DEC_FILENAME); -MODULE_FIRMWARE(IVTV_DECODE_INIT_MPEG_FILENAME); diff --git a/drivers/media/video/ivtv/ivtv-firmware.h b/drivers/media/video/ivtv/ivtv-firmware.h deleted file mode 100644 index 52bb4e5598fd..000000000000 --- a/drivers/media/video/ivtv/ivtv-firmware.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - ivtv firmware functions. - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_FIRMWARE_H -#define IVTV_FIRMWARE_H - -int ivtv_firmware_init(struct ivtv *itv); -void ivtv_firmware_versions(struct ivtv *itv); -void ivtv_halt_firmware(struct ivtv *itv); -void ivtv_init_mpeg_decoder(struct ivtv *itv); -int ivtv_firmware_check(struct ivtv *itv, char *where); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-gpio.c b/drivers/media/video/ivtv/ivtv-gpio.c deleted file mode 100644 index 8f0d07789053..000000000000 --- a/drivers/media/video/ivtv/ivtv-gpio.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - gpio functions. - Merging GPIO support into driver: - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-cards.h" -#include "ivtv-gpio.h" -#include "tuner-xc2028.h" -#include <media/tuner.h> -#include <media/v4l2-ctrls.h> - -/* - * GPIO assignment of Yuan MPG600/MPG160 - * - * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 - * OUTPUT IN1 IN0 AM3 AM2 AM1 AM0 - * INPUT DM1 DM0 - * - * IN* : Input selection - * IN1 IN0 - * 1 1 N/A - * 1 0 Line - * 0 1 N/A - * 0 0 Tuner - * - * AM* : Audio Mode - * AM3 0: Normal 1: Mixed(Sub+Main channel) - * AM2 0: Subchannel 1: Main channel - * AM1 0: Stereo 1: Mono - * AM0 0: Normal 1: Mute - * - * DM* : Detected tuner audio Mode - * DM1 0: Stereo 1: Mono - * DM0 0: Multiplex 1: Normal - * - * GPIO Initial Settings - * MPG600 MPG160 - * DIR 0x3080 0x7080 - * OUTPUT 0x000C 0x400C - * - * Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous - * for analyzing GPIO of MPG160. - * - ***************************************************************************** - * - * GPIO assignment of Avermedia M179 (per information direct from AVerMedia) - * - * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 - * OUTPUT IN0 AM0 IN1 AM1 AM2 IN2 BR0 BR1 - * INPUT - * - * IN* : Input selection - * IN0 IN1 IN2 - * * 1 * Mute - * 0 0 0 Line-In - * 1 0 0 TV Tuner Audio - * 0 0 1 FM Audio - * 1 0 1 Mute - * - * AM* : Audio Mode - * AM0 AM1 AM2 - * 0 0 0 TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP - * 0 0 1 TV Tuner Audio: L_OUT=R_OUT=SAP (SAP) - * 0 1 0 TV Tuner Audio: L_OUT=L, R_OUT=R (stereo) - * 0 1 1 TV Tuner Audio: mute - * 1 * * TV Tuner Audio: L_OUT=R_OUT=(L+R)/2 (mono) - * - * BR* : Audio Sample Rate (BR stands for bitrate for some reason) - * BR0 BR1 - * 0 0 32 kHz - * 0 1 44.1 kHz - * 1 0 48 kHz - * - * DM* : Detected tuner audio Mode - * Unknown currently - * - * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at - * AVerMedia for providing the GPIO information used to add support - * for the M179 cards. - */ - -/********************* GPIO stuffs *********************/ - -/* GPIO registers */ -#define IVTV_REG_GPIO_IN 0x9008 -#define IVTV_REG_GPIO_OUT 0x900c -#define IVTV_REG_GPIO_DIR 0x9020 - -void ivtv_reset_ir_gpio(struct ivtv *itv) -{ - int curdir, curout; - - if (itv->card->type != IVTV_CARD_PVR_150) - return; - IVTV_DEBUG_INFO("Resetting PVR150 IR\n"); - curout = read_reg(IVTV_REG_GPIO_OUT); - curdir = read_reg(IVTV_REG_GPIO_DIR); - curdir |= 0x80; - write_reg(curdir, IVTV_REG_GPIO_DIR); - curout = (curout & ~0xF) | 1; - write_reg(curout, IVTV_REG_GPIO_OUT); - /* We could use something else for smaller time */ - schedule_timeout_interruptible(msecs_to_jiffies(1)); - curout |= 2; - write_reg(curout, IVTV_REG_GPIO_OUT); - curdir &= ~0x80; - write_reg(curdir, IVTV_REG_GPIO_DIR); -} - -/* Xceive tuner reset function */ -int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) -{ - struct i2c_algo_bit_data *algo = dev; - struct ivtv *itv = algo->data; - u32 curout; - - if (cmd != XC2028_TUNER_RESET) - return 0; - IVTV_DEBUG_INFO("Resetting tuner\n"); - curout = read_reg(IVTV_REG_GPIO_OUT); - curout &= ~(1 << itv->card->xceive_pin); - write_reg(curout, IVTV_REG_GPIO_OUT); - schedule_timeout_interruptible(msecs_to_jiffies(1)); - - curout |= 1 << itv->card->xceive_pin; - write_reg(curout, IVTV_REG_GPIO_OUT); - schedule_timeout_interruptible(msecs_to_jiffies(1)); - return 0; -} - -static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd) -{ - return container_of(sd, struct ivtv, sd_gpio); -} - -static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) -{ - return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio; -} - -static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - mask = itv->card->gpio_audio_freq.mask; - switch (freq) { - case 32000: - data = itv->card->gpio_audio_freq.f32000; - break; - case 44100: - data = itv->card->gpio_audio_freq.f44100; - break; - case 48000: - default: - data = itv->card->gpio_audio_freq.f48000; - break; - } - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); - return 0; -} - -static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask; - - mask = itv->card->gpio_audio_detect.mask; - if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) - vt->rxsubchans = V4L2_TUNER_SUB_STEREO | - V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; - else - vt->rxsubchans = V4L2_TUNER_SUB_MONO; - return 0; -} - -static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - mask = itv->card->gpio_audio_mode.mask; - switch (vt->audmode) { - case V4L2_TUNER_MODE_LANG1: - data = itv->card->gpio_audio_mode.lang1; - break; - case V4L2_TUNER_MODE_LANG2: - data = itv->card->gpio_audio_mode.lang2; - break; - case V4L2_TUNER_MODE_MONO: - data = itv->card->gpio_audio_mode.mono; - break; - case V4L2_TUNER_MODE_STEREO: - case V4L2_TUNER_MODE_LANG1_LANG2: - default: - data = itv->card->gpio_audio_mode.stereo; - break; - } - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); - return 0; -} - -static int subdev_s_radio(struct v4l2_subdev *sd) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - mask = itv->card->gpio_audio_input.mask; - data = itv->card->gpio_audio_input.radio; - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); - return 0; -} - -static int subdev_s_audio_routing(struct v4l2_subdev *sd, - u32 input, u32 output, u32 config) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - if (input > 2) - return -EINVAL; - mask = itv->card->gpio_audio_input.mask; - switch (input) { - case 0: - data = itv->card->gpio_audio_input.tuner; - break; - case 1: - data = itv->card->gpio_audio_input.linein; - break; - case 2: - default: - data = itv->card->gpio_audio_input.radio; - break; - } - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); - return 0; -} - -static int subdev_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct v4l2_subdev *sd = to_sd(ctrl); - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - switch (ctrl->id) { - case V4L2_CID_AUDIO_MUTE: - mask = itv->card->gpio_audio_mute.mask; - data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0; - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | - (data & mask), IVTV_REG_GPIO_OUT); - return 0; - } - return -EINVAL; -} - - -static int subdev_log_status(struct v4l2_subdev *sd) -{ - struct ivtv *itv = sd_to_ivtv(sd); - - IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", - read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), - read_reg(IVTV_REG_GPIO_IN)); - v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name); - return 0; -} - -static int subdev_s_video_routing(struct v4l2_subdev *sd, - u32 input, u32 output, u32 config) -{ - struct ivtv *itv = sd_to_ivtv(sd); - u16 mask, data; - - if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */ - return -EINVAL; - mask = itv->card->gpio_video_input.mask; - if (input == 0) - data = itv->card->gpio_video_input.tuner; - else if (input == 1) - data = itv->card->gpio_video_input.composite; - else - data = itv->card->gpio_video_input.svideo; - if (mask) - write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); - return 0; -} - -static const struct v4l2_ctrl_ops gpio_ctrl_ops = { - .s_ctrl = subdev_s_ctrl, -}; - -static const struct v4l2_subdev_core_ops subdev_core_ops = { - .log_status = subdev_log_status, - .g_ext_ctrls = v4l2_subdev_g_ext_ctrls, - .try_ext_ctrls = v4l2_subdev_try_ext_ctrls, - .s_ext_ctrls = v4l2_subdev_s_ext_ctrls, - .g_ctrl = v4l2_subdev_g_ctrl, - .s_ctrl = v4l2_subdev_s_ctrl, - .queryctrl = v4l2_subdev_queryctrl, - .querymenu = v4l2_subdev_querymenu, -}; - -static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = { - .s_radio = subdev_s_radio, - .g_tuner = subdev_g_tuner, - .s_tuner = subdev_s_tuner, -}; - -static const struct v4l2_subdev_audio_ops subdev_audio_ops = { - .s_clock_freq = subdev_s_clock_freq, - .s_routing = subdev_s_audio_routing, -}; - -static const struct v4l2_subdev_video_ops subdev_video_ops = { - .s_routing = subdev_s_video_routing, -}; - -static const struct v4l2_subdev_ops subdev_ops = { - .core = &subdev_core_ops, - .tuner = &subdev_tuner_ops, - .audio = &subdev_audio_ops, - .video = &subdev_video_ops, -}; - -int ivtv_gpio_init(struct ivtv *itv) -{ - u16 pin = 0; - - if (itv->card->xceive_pin) - pin = 1 << itv->card->xceive_pin; - - if ((itv->card->gpio_init.direction | pin) == 0) - return 0; - - IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", - read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT)); - - /* init output data then direction */ - write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT); - write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR); - v4l2_subdev_init(&itv->sd_gpio, &subdev_ops); - snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->v4l2_dev.name); - itv->sd_gpio.grp_id = IVTV_HW_GPIO; - v4l2_ctrl_handler_init(&itv->hdl_gpio, 1); - v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops, - V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); - if (itv->hdl_gpio.error) - return itv->hdl_gpio.error; - itv->sd_gpio.ctrl_handler = &itv->hdl_gpio; - v4l2_ctrl_handler_setup(&itv->hdl_gpio); - return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio); -} diff --git a/drivers/media/video/ivtv/ivtv-gpio.h b/drivers/media/video/ivtv/ivtv-gpio.h deleted file mode 100644 index 0b5d19c8ecb4..000000000000 --- a/drivers/media/video/ivtv/ivtv-gpio.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - gpio functions. - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_GPIO_H -#define IVTV_GPIO_H - -/* GPIO stuff */ -int ivtv_gpio_init(struct ivtv *itv); -void ivtv_reset_ir_gpio(struct ivtv *itv); -int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c deleted file mode 100644 index d47f41a0ef66..000000000000 --- a/drivers/media/video/ivtv/ivtv-i2c.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - I2C functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - This file includes an i2c implementation that was reverse engineered - from the Hauppauge windows driver. Older ivtv versions used i2c-algo-bit, - which whilst fine under most circumstances, had trouble with the Zilog - CPU on the PVR-150 which handles IR functions (occasional inability to - communicate with the chip until it was reset) and also with the i2c - bus being completely unreachable when multiple PVR cards were present. - - The implementation is very similar to i2c-algo-bit, but there are enough - subtle differences that the two are hard to merge. The general strategy - employed by i2c-algo-bit is to use udelay() to implement the timing - when putting out bits on the scl/sda lines. The general strategy taken - here is to poll the lines for state changes (see ivtv_waitscl and - ivtv_waitsda). In addition there are small delays at various locations - which poll the SCL line 5 times (ivtv_scldelay). I would guess that - since this is memory mapped I/O that the length of those delays is tied - to the PCI bus clock. There is some extra code to do with recovery - and retries. Since it is not known what causes the actual i2c problems - in the first place, the only goal if one was to attempt to use - i2c-algo-bit would be to try to make it follow the same code path. - This would be a lot of work, and I'm also not convinced that it would - provide a generic benefit to i2c-algo-bit. Therefore consider this - an engineering solution -- not pretty, but it works. - - Some more general comments about what we are doing: - - The i2c bus is a 2 wire serial bus, with clock (SCL) and data (SDA) - lines. To communicate on the bus (as a master, we don't act as a slave), - we first initiate a start condition (ivtv_start). We then write the - address of the device that we want to communicate with, along with a flag - that indicates whether this is a read or a write. The slave then issues - an ACK signal (ivtv_ack), which tells us that it is ready for reading / - writing. We then proceed with reading or writing (ivtv_read/ivtv_write), - and finally issue a stop condition (ivtv_stop) to make the bus available - to other masters. - - There is an additional form of transaction where a write may be - immediately followed by a read. In this case, there is no intervening - stop condition. (Only the msp3400 chip uses this method of data transfer). - */ - -#include "ivtv-driver.h" -#include "ivtv-cards.h" -#include "ivtv-gpio.h" -#include "ivtv-i2c.h" -#include <media/cx25840.h> - -/* i2c implementation for cx23415/6 chip, ivtv project. - * Author: Kevin Thayer (nufan_wfk at yahoo.com) - */ -/* i2c stuff */ -#define IVTV_REG_I2C_SETSCL_OFFSET 0x7000 -#define IVTV_REG_I2C_SETSDA_OFFSET 0x7004 -#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008 -#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c - -#define IVTV_CS53L32A_I2C_ADDR 0x11 -#define IVTV_M52790_I2C_ADDR 0x48 -#define IVTV_CX25840_I2C_ADDR 0x44 -#define IVTV_SAA7115_I2C_ADDR 0x21 -#define IVTV_SAA7127_I2C_ADDR 0x44 -#define IVTV_SAA717x_I2C_ADDR 0x21 -#define IVTV_MSP3400_I2C_ADDR 0x40 -#define IVTV_HAUPPAUGE_I2C_ADDR 0x50 -#define IVTV_WM8739_I2C_ADDR 0x1a -#define IVTV_WM8775_I2C_ADDR 0x1b -#define IVTV_TEA5767_I2C_ADDR 0x60 -#define IVTV_UPD64031A_I2C_ADDR 0x12 -#define IVTV_UPD64083_I2C_ADDR 0x5c -#define IVTV_VP27SMPX_I2C_ADDR 0x5b -#define IVTV_M52790_I2C_ADDR 0x48 -#define IVTV_AVERMEDIA_IR_RX_I2C_ADDR 0x40 -#define IVTV_HAUP_EXT_IR_RX_I2C_ADDR 0x1a -#define IVTV_HAUP_INT_IR_RX_I2C_ADDR 0x18 -#define IVTV_Z8F0811_IR_TX_I2C_ADDR 0x70 -#define IVTV_Z8F0811_IR_RX_I2C_ADDR 0x71 -#define IVTV_ADAPTEC_IR_ADDR 0x6b - -/* This array should match the IVTV_HW_ defines */ -static const u8 hw_addrs[] = { - IVTV_CX25840_I2C_ADDR, - IVTV_SAA7115_I2C_ADDR, - IVTV_SAA7127_I2C_ADDR, - IVTV_MSP3400_I2C_ADDR, - 0, - IVTV_WM8775_I2C_ADDR, - IVTV_CS53L32A_I2C_ADDR, - 0, - IVTV_SAA7115_I2C_ADDR, - IVTV_UPD64031A_I2C_ADDR, - IVTV_UPD64083_I2C_ADDR, - IVTV_SAA717x_I2C_ADDR, - IVTV_WM8739_I2C_ADDR, - IVTV_VP27SMPX_I2C_ADDR, - IVTV_M52790_I2C_ADDR, - 0, /* IVTV_HW_GPIO dummy driver ID */ - IVTV_AVERMEDIA_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_AVER */ - IVTV_HAUP_EXT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ - IVTV_HAUP_INT_IR_RX_I2C_ADDR, /* IVTV_HW_I2C_IR_RX_HAUP_INT */ - IVTV_Z8F0811_IR_TX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_TX_HAUP */ - IVTV_Z8F0811_IR_RX_I2C_ADDR, /* IVTV_HW_Z8F0811_IR_RX_HAUP */ - IVTV_ADAPTEC_IR_ADDR, /* IVTV_HW_I2C_IR_RX_ADAPTEC */ -}; - -/* This array should match the IVTV_HW_ defines */ -static const char * const hw_devicenames[] = { - "cx25840", - "saa7115", - "saa7127_auto", /* saa7127 or saa7129 */ - "msp3400", - "tuner", - "wm8775", - "cs53l32a", - "tveeprom", - "saa7114", - "upd64031a", - "upd64083", - "saa717x", - "wm8739", - "vp27smpx", - "m52790", - "gpio", - "ir_video", /* IVTV_HW_I2C_IR_RX_AVER */ - "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_EXT */ - "ir_video", /* IVTV_HW_I2C_IR_RX_HAUP_INT */ - "ir_tx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_TX_HAUP */ - "ir_rx_z8f0811_haup", /* IVTV_HW_Z8F0811_IR_RX_HAUP */ - "ir_video", /* IVTV_HW_I2C_IR_RX_ADAPTEC */ -}; - -static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) -{ - unsigned char keybuf[4]; - - keybuf[0] = 0x00; - i2c_master_send(ir->c, keybuf, 1); - /* poll IR chip */ - if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { - return 0; - } - - /* key pressed ? */ - if (keybuf[2] == 0xff) - return 0; - - /* remove repeat bit */ - keybuf[2] &= 0x7f; - keybuf[3] |= 0x80; - - *ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24; - *ir_raw = *ir_key; - - return 1; -} - -static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr) -{ - struct i2c_board_info info; - struct i2c_adapter *adap = &itv->i2c_adap; - struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data; - unsigned short addr_list[2] = { addr, I2C_CLIENT_END }; - - /* Only allow one IR transmitter to be registered per board */ - if (hw & IVTV_HW_IR_TX_ANY) { - if (itv->hw_flags & IVTV_HW_IR_TX_ANY) - return -1; - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, type, I2C_NAME_SIZE); - return i2c_new_probed_device(adap, &info, addr_list, NULL) - == NULL ? -1 : 0; - } - - /* Only allow one IR receiver to be registered per board */ - if (itv->hw_flags & IVTV_HW_IR_RX_ANY) - return -1; - - /* Our default information for ir-kbd-i2c.c to use */ - switch (hw) { - case IVTV_HW_I2C_IR_RX_AVER: - init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS; - init_data->internal_get_key_func = - IR_KBD_GET_KEY_AVERMEDIA_CARDBUS; - init_data->type = RC_TYPE_OTHER; - init_data->name = "AVerMedia AVerTV card"; - break; - case IVTV_HW_I2C_IR_RX_HAUP_EXT: - case IVTV_HW_I2C_IR_RX_HAUP_INT: - init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP; - init_data->type = RC_TYPE_RC5; - init_data->name = itv->card_name; - break; - case IVTV_HW_Z8F0811_IR_RX_HAUP: - /* Default to grey remote */ - init_data->ir_codes = RC_MAP_HAUPPAUGE; - init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR; - init_data->type = RC_TYPE_RC5; - init_data->name = itv->card_name; - break; - case IVTV_HW_I2C_IR_RX_ADAPTEC: - init_data->get_key = get_key_adaptec; - init_data->name = itv->card_name; - /* FIXME: The protocol and RC_MAP needs to be corrected */ - init_data->ir_codes = RC_MAP_EMPTY; - init_data->type = RC_TYPE_UNKNOWN; - break; - } - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.platform_data = init_data; - strlcpy(info.type, type, I2C_NAME_SIZE); - - return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ? - -1 : 0; -} - -/* Instantiate the IR receiver device using probing -- undesirable */ -struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv) -{ - struct i2c_board_info info; - /* - * The external IR receiver is at i2c address 0x34. - * The internal IR receiver is at i2c address 0x30. - * - * In theory, both can be fitted, and Hauppauge suggests an external - * overrides an internal. That's why we probe 0x1a (~0x34) first. CB - * - * Some of these addresses we probe may collide with other i2c address - * allocations, so this function must be called after all other i2c - * devices we care about are registered. - */ - const unsigned short addr_list[] = { - 0x1a, /* Hauppauge IR external - collides with WM8739 */ - 0x18, /* Hauppauge IR internal */ - I2C_CLIENT_END - }; - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL); -} - -int ivtv_i2c_register(struct ivtv *itv, unsigned idx) -{ - struct v4l2_subdev *sd; - struct i2c_adapter *adap = &itv->i2c_adap; - const char *type = hw_devicenames[idx]; - u32 hw = 1 << idx; - - if (idx >= ARRAY_SIZE(hw_addrs)) - return -1; - if (hw == IVTV_HW_TUNER) { - /* special tuner handling */ - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, - itv->card_i2c->radio); - if (sd) - sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, - itv->card_i2c->demod); - if (sd) - sd->grp_id = 1 << idx; - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0, - itv->card_i2c->tv); - if (sd) - sd->grp_id = 1 << idx; - return sd ? 0 : -1; - } - - if (hw & IVTV_HW_IR_ANY) - return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]); - - /* Is it not an I2C device or one we do not wish to register? */ - if (!hw_addrs[idx]) - return -1; - - /* It's an I2C device other than an analog tuner or IR chip */ - if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) { - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, type, 0, I2C_ADDRS(hw_addrs[idx])); - } else if (hw == IVTV_HW_CX25840) { - struct cx25840_platform_data pdata; - struct i2c_board_info cx25840_info = { - .type = "cx25840", - .addr = hw_addrs[idx], - .platform_data = &pdata, - }; - - pdata.pvr150_workaround = itv->pvr150_workaround; - sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap, - &cx25840_info, NULL); - } else { - sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, - adap, type, hw_addrs[idx], NULL); - } - if (sd) - sd->grp_id = 1 << idx; - return sd ? 0 : -1; -} - -struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw) -{ - struct v4l2_subdev *result = NULL; - struct v4l2_subdev *sd; - - spin_lock(&itv->v4l2_dev.lock); - v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) { - if (sd->grp_id == hw) { - result = sd; - break; - } - } - spin_unlock(&itv->v4l2_dev.lock); - return result; -} - -/* Set the serial clock line to the desired state */ -static void ivtv_setscl(struct ivtv *itv, int state) -{ - /* write them out */ - /* write bits are inverted */ - write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET); -} - -/* Set the serial data line to the desired state */ -static void ivtv_setsda(struct ivtv *itv, int state) -{ - /* write them out */ - /* write bits are inverted */ - write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET); -} - -/* Read the serial clock line */ -static int ivtv_getscl(struct ivtv *itv) -{ - return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1; -} - -/* Read the serial data line */ -static int ivtv_getsda(struct ivtv *itv) -{ - return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1; -} - -/* Implement a short delay by polling the serial clock line */ -static void ivtv_scldelay(struct ivtv *itv) -{ - int i; - - for (i = 0; i < 5; ++i) - ivtv_getscl(itv); -} - -/* Wait for the serial clock line to become set to a specific value */ -static int ivtv_waitscl(struct ivtv *itv, int val) -{ - int i; - - ivtv_scldelay(itv); - for (i = 0; i < 1000; ++i) { - if (ivtv_getscl(itv) == val) - return 1; - } - return 0; -} - -/* Wait for the serial data line to become set to a specific value */ -static int ivtv_waitsda(struct ivtv *itv, int val) -{ - int i; - - ivtv_scldelay(itv); - for (i = 0; i < 1000; ++i) { - if (ivtv_getsda(itv) == val) - return 1; - } - return 0; -} - -/* Wait for the slave to issue an ACK */ -static int ivtv_ack(struct ivtv *itv) -{ - int ret = 0; - - if (ivtv_getscl(itv) == 1) { - IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n"); - ivtv_setscl(itv, 0); - if (!ivtv_waitscl(itv, 0)) { - IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n"); - return -EREMOTEIO; - } - } - ivtv_setsda(itv, 1); - ivtv_scldelay(itv); - ivtv_setscl(itv, 1); - if (!ivtv_waitsda(itv, 0)) { - IVTV_DEBUG_I2C("Slave did not ack\n"); - ret = -EREMOTEIO; - } - ivtv_setscl(itv, 0); - if (!ivtv_waitscl(itv, 0)) { - IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n"); - ret = -EREMOTEIO; - } - return ret; -} - -/* Write a single byte to the i2c bus and wait for the slave to ACK */ -static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte) -{ - int i, bit; - - IVTV_DEBUG_HI_I2C("write %x\n",byte); - for (i = 0; i < 8; ++i, byte<<=1) { - ivtv_setscl(itv, 0); - if (!ivtv_waitscl(itv, 0)) { - IVTV_DEBUG_I2C("Error setting SCL low\n"); - return -EREMOTEIO; - } - bit = (byte>>7)&1; - ivtv_setsda(itv, bit); - if (!ivtv_waitsda(itv, bit)) { - IVTV_DEBUG_I2C("Error setting SDA\n"); - return -EREMOTEIO; - } - ivtv_setscl(itv, 1); - if (!ivtv_waitscl(itv, 1)) { - IVTV_DEBUG_I2C("Slave not ready for bit\n"); - return -EREMOTEIO; - } - } - ivtv_setscl(itv, 0); - if (!ivtv_waitscl(itv, 0)) { - IVTV_DEBUG_I2C("Error setting SCL low\n"); - return -EREMOTEIO; - } - return ivtv_ack(itv); -} - -/* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the - final byte) */ -static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack) -{ - int i; - - *byte = 0; - - ivtv_setsda(itv, 1); - ivtv_scldelay(itv); - for (i = 0; i < 8; ++i) { - ivtv_setscl(itv, 0); - ivtv_scldelay(itv); - ivtv_setscl(itv, 1); - if (!ivtv_waitscl(itv, 1)) { - IVTV_DEBUG_I2C("Error setting SCL high\n"); - return -EREMOTEIO; - } - *byte = ((*byte)<<1)|ivtv_getsda(itv); - } - ivtv_setscl(itv, 0); - ivtv_scldelay(itv); - ivtv_setsda(itv, nack); - ivtv_scldelay(itv); - ivtv_setscl(itv, 1); - ivtv_scldelay(itv); - ivtv_setscl(itv, 0); - ivtv_scldelay(itv); - IVTV_DEBUG_HI_I2C("read %x\n",*byte); - return 0; -} - -/* Issue a start condition on the i2c bus to alert slaves to prepare for - an address write */ -static int ivtv_start(struct ivtv *itv) -{ - int sda; - - sda = ivtv_getsda(itv); - if (sda != 1) { - IVTV_DEBUG_HI_I2C("SDA was low at start\n"); - ivtv_setsda(itv, 1); - if (!ivtv_waitsda(itv, 1)) { - IVTV_DEBUG_I2C("SDA stuck low\n"); - return -EREMOTEIO; - } - } - if (ivtv_getscl(itv) != 1) { - ivtv_setscl(itv, 1); - if (!ivtv_waitscl(itv, 1)) { - IVTV_DEBUG_I2C("SCL stuck low at start\n"); - return -EREMOTEIO; - } - } - ivtv_setsda(itv, 0); - ivtv_scldelay(itv); - return 0; -} - -/* Issue a stop condition on the i2c bus to release it */ -static int ivtv_stop(struct ivtv *itv) -{ - int i; - - if (ivtv_getscl(itv) != 0) { - IVTV_DEBUG_HI_I2C("SCL not low when stopping\n"); - ivtv_setscl(itv, 0); - if (!ivtv_waitscl(itv, 0)) { - IVTV_DEBUG_I2C("SCL could not be set low\n"); - } - } - ivtv_setsda(itv, 0); - ivtv_scldelay(itv); - ivtv_setscl(itv, 1); - if (!ivtv_waitscl(itv, 1)) { - IVTV_DEBUG_I2C("SCL could not be set high\n"); - return -EREMOTEIO; - } - ivtv_scldelay(itv); - ivtv_setsda(itv, 1); - if (!ivtv_waitsda(itv, 1)) { - IVTV_DEBUG_I2C("resetting I2C\n"); - for (i = 0; i < 16; ++i) { - ivtv_setscl(itv, 0); - ivtv_scldelay(itv); - ivtv_setscl(itv, 1); - ivtv_scldelay(itv); - ivtv_setsda(itv, 1); - } - ivtv_waitsda(itv, 1); - return -EREMOTEIO; - } - return 0; -} - -/* Write a message to the given i2c slave. do_stop may be 0 to prevent - issuing the i2c stop condition (when following with a read) */ -static int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop) -{ - int retry, ret = -EREMOTEIO; - u32 i; - - for (retry = 0; ret != 0 && retry < 8; ++retry) { - ret = ivtv_start(itv); - - if (ret == 0) { - ret = ivtv_sendbyte(itv, addr<<1); - for (i = 0; ret == 0 && i < len; ++i) - ret = ivtv_sendbyte(itv, data[i]); - } - if (ret != 0 || do_stop) { - ivtv_stop(itv); - } - } - if (ret) - IVTV_DEBUG_I2C("i2c write to %x failed\n", addr); - return ret; -} - -/* Read data from the given i2c slave. A stop condition is always issued. */ -static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len) -{ - int retry, ret = -EREMOTEIO; - u32 i; - - for (retry = 0; ret != 0 && retry < 8; ++retry) { - ret = ivtv_start(itv); - if (ret == 0) - ret = ivtv_sendbyte(itv, (addr << 1) | 1); - for (i = 0; ret == 0 && i < len; ++i) { - ret = ivtv_readbyte(itv, &data[i], i == len - 1); - } - ivtv_stop(itv); - } - if (ret) - IVTV_DEBUG_I2C("i2c read from %x failed\n", addr); - return ret; -} - -/* Kernel i2c transfer implementation. Takes a number of messages to be read - or written. If a read follows a write, this will occur without an - intervening stop condition */ -static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) -{ - struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap); - struct ivtv *itv = to_ivtv(v4l2_dev); - int retval; - int i; - - mutex_lock(&itv->i2c_bus_lock); - for (i = retval = 0; retval == 0 && i < num; i++) { - if (msgs[i].flags & I2C_M_RD) - retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len); - else { - /* if followed by a read, don't stop */ - int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD); - - retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop); - } - } - mutex_unlock(&itv->i2c_bus_lock); - return retval ? retval : num; -} - -/* Kernel i2c capabilities */ -static u32 ivtv_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm ivtv_algo = { - .master_xfer = ivtv_xfer, - .functionality = ivtv_functionality, -}; - -/* template for our-bit banger */ -static struct i2c_adapter ivtv_i2c_adap_hw_template = { - .name = "ivtv i2c driver", - .algo = &ivtv_algo, - .algo_data = NULL, /* filled from template */ - .owner = THIS_MODULE, -}; - -static void ivtv_setscl_old(void *data, int state) -{ - struct ivtv *itv = (struct ivtv *)data; - - if (state) - itv->i2c_state |= 0x01; - else - itv->i2c_state &= ~0x01; - - /* write them out */ - /* write bits are inverted */ - write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET); -} - -static void ivtv_setsda_old(void *data, int state) -{ - struct ivtv *itv = (struct ivtv *)data; - - if (state) - itv->i2c_state |= 0x01; - else - itv->i2c_state &= ~0x01; - - /* write them out */ - /* write bits are inverted */ - write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET); -} - -static int ivtv_getscl_old(void *data) -{ - struct ivtv *itv = (struct ivtv *)data; - - return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1; -} - -static int ivtv_getsda_old(void *data) -{ - struct ivtv *itv = (struct ivtv *)data; - - return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1; -} - -/* template for i2c-bit-algo */ -static struct i2c_adapter ivtv_i2c_adap_template = { - .name = "ivtv i2c driver", - .algo = NULL, /* set by i2c-algo-bit */ - .algo_data = NULL, /* filled from template */ - .owner = THIS_MODULE, -}; - -#define IVTV_ALGO_BIT_TIMEOUT (2) /* seconds */ - -static const struct i2c_algo_bit_data ivtv_i2c_algo_template = { - .setsda = ivtv_setsda_old, - .setscl = ivtv_setscl_old, - .getsda = ivtv_getsda_old, - .getscl = ivtv_getscl_old, - .udelay = IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2, /* microseconds */ - .timeout = IVTV_ALGO_BIT_TIMEOUT * HZ, /* jiffies */ -}; - -static struct i2c_client ivtv_i2c_client_template = { - .name = "ivtv internal", -}; - -/* init + register i2c adapter */ -int init_ivtv_i2c(struct ivtv *itv) -{ - int retval; - - IVTV_DEBUG_I2C("i2c init\n"); - - /* Sanity checks for the I2C hardware arrays. They must be the - * same size. - */ - if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs)) { - IVTV_ERR("Mismatched I2C hardware arrays\n"); - return -ENODEV; - } - if (itv->options.newi2c > 0) { - memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template, - sizeof(struct i2c_adapter)); - } else { - memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template, - sizeof(struct i2c_adapter)); - memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template, - sizeof(struct i2c_algo_bit_data)); - } - itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2; - itv->i2c_algo.data = itv; - itv->i2c_adap.algo_data = &itv->i2c_algo; - - sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d", - itv->instance); - i2c_set_adapdata(&itv->i2c_adap, &itv->v4l2_dev); - - memcpy(&itv->i2c_client, &ivtv_i2c_client_template, - sizeof(struct i2c_client)); - itv->i2c_client.adapter = &itv->i2c_adap; - itv->i2c_adap.dev.parent = &itv->pdev->dev; - - IVTV_DEBUG_I2C("setting scl and sda to 1\n"); - ivtv_setscl(itv, 1); - ivtv_setsda(itv, 1); - - if (itv->options.newi2c > 0) - retval = i2c_add_adapter(&itv->i2c_adap); - else - retval = i2c_bit_add_bus(&itv->i2c_adap); - - return retval; -} - -void exit_ivtv_i2c(struct ivtv *itv) -{ - IVTV_DEBUG_I2C("i2c exit\n"); - - i2c_del_adapter(&itv->i2c_adap); -} diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h deleted file mode 100644 index 7b9ec1cfeb80..000000000000 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - I2C functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_I2C_H -#define IVTV_I2C_H - -struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv); -int ivtv_i2c_register(struct ivtv *itv, unsigned idx); -struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); - -/* init + register i2c adapter */ -int init_ivtv_i2c(struct ivtv *itv); -void exit_ivtv_i2c(struct ivtv *itv); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c deleted file mode 100644 index 32a591062d0b..000000000000 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ /dev/null @@ -1,1899 +0,0 @@ -/* - ioctl system call - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-version.h" -#include "ivtv-mailbox.h" -#include "ivtv-i2c.h" -#include "ivtv-queue.h" -#include "ivtv-fileops.h" -#include "ivtv-vbi.h" -#include "ivtv-routing.h" -#include "ivtv-streams.h" -#include "ivtv-yuv.h" -#include "ivtv-ioctl.h" -#include "ivtv-gpio.h" -#include "ivtv-controls.h" -#include "ivtv-cards.h" -#include <media/saa7127.h> -#include <media/tveeprom.h> -#include <media/v4l2-chip-ident.h> -#include <media/v4l2-event.h> -#include <linux/dvb/audio.h> - -u16 ivtv_service2vbi(int type) -{ - switch (type) { - case V4L2_SLICED_TELETEXT_B: - return IVTV_SLICED_TYPE_TELETEXT_B; - case V4L2_SLICED_CAPTION_525: - return IVTV_SLICED_TYPE_CAPTION_525; - case V4L2_SLICED_WSS_625: - return IVTV_SLICED_TYPE_WSS_625; - case V4L2_SLICED_VPS: - return IVTV_SLICED_TYPE_VPS; - default: - return 0; - } -} - -static int valid_service_line(int field, int line, int is_pal) -{ - return (is_pal && line >= 6 && (line != 23 || field == 0)) || - (!is_pal && line >= 10 && line < 22); -} - -static u16 select_service_from_set(int field, int line, u16 set, int is_pal) -{ - u16 valid_set = (is_pal ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525); - int i; - - set = set & valid_set; - if (set == 0 || !valid_service_line(field, line, is_pal)) { - return 0; - } - if (!is_pal) { - if (line == 21 && (set & V4L2_SLICED_CAPTION_525)) - return V4L2_SLICED_CAPTION_525; - } - else { - if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS)) - return V4L2_SLICED_VPS; - if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625)) - return V4L2_SLICED_WSS_625; - if (line == 23) - return 0; - } - for (i = 0; i < 32; i++) { - if ((1 << i) & set) - return 1 << i; - } - return 0; -} - -void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) -{ - u16 set = fmt->service_set; - int f, l; - - fmt->service_set = 0; - for (f = 0; f < 2; f++) { - for (l = 0; l < 24; l++) { - fmt->service_lines[f][l] = select_service_from_set(f, l, set, is_pal); - } - } -} - -static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) -{ - int f, l; - - for (f = 0; f < 2; f++) { - for (l = 0; l < 24; l++) { - fmt->service_lines[f][l] = select_service_from_set(f, l, fmt->service_lines[f][l], is_pal); - } - } -} - -u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) -{ - int f, l; - u16 set = 0; - - for (f = 0; f < 2; f++) { - for (l = 0; l < 24; l++) { - set |= fmt->service_lines[f][l]; - } - } - return set; -} - -void ivtv_set_osd_alpha(struct ivtv *itv) -{ - ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3, - itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state); - ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key); -} - -int ivtv_set_speed(struct ivtv *itv, int speed) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - int single_step = (speed == 1 || speed == -1); - DEFINE_WAIT(wait); - - if (speed == 0) speed = 1000; - - /* No change? */ - if (speed == itv->speed && !single_step) - return 0; - - if (single_step && (speed < 0) == (itv->speed < 0)) { - /* Single step video and no need to change direction */ - ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0); - itv->speed = speed; - return 0; - } - if (single_step) - /* Need to change direction */ - speed = speed < 0 ? -1000 : 1000; - - data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0; - data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0; - data[1] = (speed < 0); - data[2] = speed < 0 ? 3 : 7; - data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames); - data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0; - data[5] = 0; - data[6] = 0; - - if (speed == 1500 || speed == -1500) data[0] |= 1; - else if (speed == 2000 || speed == -2000) data[0] |= 2; - else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed); - else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed); - - /* If not decoding, just change speed setting */ - if (atomic_read(&itv->decoding) > 0) { - int got_sig = 0; - - /* Stop all DMA and decoding activity */ - ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0); - - /* Wait for any DMA to finish */ - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) { - got_sig = signal_pending(current); - if (got_sig) - break; - got_sig = 0; - schedule(); - } - finish_wait(&itv->dma_waitq, &wait); - mutex_lock(&itv->serialize_lock); - if (got_sig) - return -EINTR; - - /* Change Speed safely */ - ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data); - IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - data[0], data[1], data[2], data[3], data[4], data[5], data[6]); - } - if (single_step) { - speed = (speed < 0) ? -1 : 1; - ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0); - } - itv->speed = speed; - return 0; -} - -static int ivtv_validate_speed(int cur_speed, int new_speed) -{ - int fact = new_speed < 0 ? -1 : 1; - int s; - - if (cur_speed == 0) - cur_speed = 1000; - if (new_speed < 0) - new_speed = -new_speed; - if (cur_speed < 0) - cur_speed = -cur_speed; - - if (cur_speed <= new_speed) { - if (new_speed > 1500) - return fact * 2000; - if (new_speed > 1000) - return fact * 1500; - } - else { - if (new_speed >= 2000) - return fact * 2000; - if (new_speed >= 1500) - return fact * 1500; - if (new_speed >= 1000) - return fact * 1000; - } - if (new_speed == 0) - return 1000; - if (new_speed == 1 || new_speed == 1000) - return fact * new_speed; - - s = new_speed; - new_speed = 1000 / new_speed; - if (1000 / cur_speed == new_speed) - new_speed += (cur_speed < s) ? -1 : 1; - if (new_speed > 60) return 1000 / (fact * 60); - return 1000 / (fact * new_speed); -} - -static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, - struct v4l2_decoder_cmd *dc, int try) -{ - struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - - switch (dc->cmd) { - case V4L2_DEC_CMD_START: { - dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO; - dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed); - if (dc->start.speed < 0) - dc->start.format = V4L2_DEC_START_FMT_GOP; - else - dc->start.format = V4L2_DEC_START_FMT_NONE; - if (dc->start.speed != 500 && dc->start.speed != 1500) - dc->flags = dc->start.speed == 1000 ? 0 : - V4L2_DEC_CMD_START_MUTE_AUDIO; - if (try) break; - - itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO; - if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) - return -EBUSY; - if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { - /* forces ivtv_set_speed to be called */ - itv->speed = 0; - } - return ivtv_start_decoding(id, dc->start.speed); - } - - case V4L2_DEC_CMD_STOP: - dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK; - if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) - dc->stop.pts = 0; - if (try) break; - if (atomic_read(&itv->decoding) == 0) - return 0; - if (itv->output_mode != OUT_MPG) - return -EBUSY; - - itv->output_mode = OUT_NONE; - return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts); - - case V4L2_DEC_CMD_PAUSE: - dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK; - if (try) break; - if (itv->output_mode != OUT_MPG) - return -EBUSY; - if (atomic_read(&itv->decoding) > 0) { - ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, - (dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0); - set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); - } - break; - - case V4L2_DEC_CMD_RESUME: - dc->flags = 0; - if (try) break; - if (itv->output_mode != OUT_MPG) - return -EBUSY; - if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { - int speed = itv->speed; - itv->speed = 0; - return ivtv_start_decoding(id, speed); - } - break; - - default: - return -EINVAL; - } - return 0; -} - -static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - - vbifmt->reserved[0] = 0; - vbifmt->reserved[1] = 0; - if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) - return -EINVAL; - vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; - if (itv->is_60hz) { - vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525; - vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525; - } else { - vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; - vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; - } - vbifmt->service_set = ivtv_get_service_set(vbifmt); - return 0; -} - -static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - - pixfmt->width = itv->cxhdl.width; - pixfmt->height = itv->cxhdl.height; - pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - pixfmt->field = V4L2_FIELD_INTERLACED; - pixfmt->priv = 0; - if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { - pixfmt->pixelformat = V4L2_PIX_FMT_HM12; - /* YUV size is (Y=(h*720) + UV=(h*(720/2))) */ - pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2; - pixfmt->bytesperline = 720; - } else { - pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; - pixfmt->sizeimage = 128 * 1024; - pixfmt->bytesperline = 0; - } - return 0; -} - -static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi; - - vbifmt->sampling_rate = 27000000; - vbifmt->offset = 248; - vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4; - vbifmt->sample_format = V4L2_PIX_FMT_GREY; - vbifmt->start[0] = itv->vbi.start[0]; - vbifmt->start[1] = itv->vbi.start[1]; - vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count; - vbifmt->flags = 0; - vbifmt->reserved[0] = 0; - vbifmt->reserved[1] = 0; - return 0; -} - -static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - - vbifmt->reserved[0] = 0; - vbifmt->reserved[1] = 0; - vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; - - if (id->type == IVTV_DEC_STREAM_TYPE_VBI) { - vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : - V4L2_SLICED_VBI_525; - ivtv_expand_service_set(vbifmt, itv->is_50hz); - return 0; - } - - v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt); - vbifmt->service_set = ivtv_get_service_set(vbifmt); - return 0; -} - -static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct v4l2_pix_format *pixfmt = &fmt->fmt.pix; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - pixfmt->width = itv->main_rect.width; - pixfmt->height = itv->main_rect.height; - pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M; - pixfmt->field = V4L2_FIELD_INTERLACED; - pixfmt->priv = 0; - if (id->type == IVTV_DEC_STREAM_TYPE_YUV) { - switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) { - case IVTV_YUV_MODE_INTERLACED: - pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ? - V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB; - break; - case IVTV_YUV_MODE_PROGRESSIVE: - pixfmt->field = V4L2_FIELD_NONE; - break; - default: - pixfmt->field = V4L2_FIELD_ANY; - break; - } - pixfmt->pixelformat = V4L2_PIX_FMT_HM12; - pixfmt->bytesperline = 720; - pixfmt->width = itv->yuv_info.v4l2_src_w; - pixfmt->height = itv->yuv_info.v4l2_src_h; - /* YUV size is (Y=(h*w) + UV=(h*(w/2))) */ - pixfmt->sizeimage = - 1080 * ((pixfmt->height + 31) & ~31); - } else { - pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; - pixfmt->sizeimage = 128 * 1024; - pixfmt->bytesperline = 0; - } - return 0; -} - -static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - struct v4l2_window *winfmt = &fmt->fmt.win; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - winfmt->chromakey = itv->osd_chroma_key; - winfmt->global_alpha = itv->osd_global_alpha; - winfmt->field = V4L2_FIELD_INTERLACED; - winfmt->clips = NULL; - winfmt->clipcount = 0; - winfmt->bitmap = NULL; - winfmt->w.top = winfmt->w.left = 0; - winfmt->w.width = itv->osd_rect.width; - winfmt->w.height = itv->osd_rect.height; - return 0; -} - -static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) -{ - return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt); -} - -static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - int w = fmt->fmt.pix.width; - int h = fmt->fmt.pix.height; - int min_h = 2; - - w = min(w, 720); - w = max(w, 2); - if (id->type == IVTV_ENC_STREAM_TYPE_YUV) { - /* YUV height must be a multiple of 32 */ - h &= ~0x1f; - min_h = 32; - } - h = min(h, itv->is_50hz ? 576 : 480); - h = max(h, min_h); - ivtv_g_fmt_vid_cap(file, fh, fmt); - fmt->fmt.pix.width = w; - fmt->fmt.pix.height = h; - return 0; -} - -static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - return ivtv_g_fmt_vbi_cap(file, fh, fmt); -} - -static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - - if (id->type == IVTV_DEC_STREAM_TYPE_VBI) - return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt); - - /* set sliced VBI capture format */ - vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36; - vbifmt->reserved[0] = 0; - vbifmt->reserved[1] = 0; - - if (vbifmt->service_set) - ivtv_expand_service_set(vbifmt, itv->is_50hz); - check_service_set(vbifmt, itv->is_50hz); - vbifmt->service_set = ivtv_get_service_set(vbifmt); - return 0; -} - -static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv_open_id *id = fh2id(fh); - s32 w = fmt->fmt.pix.width; - s32 h = fmt->fmt.pix.height; - int field = fmt->fmt.pix.field; - int ret = ivtv_g_fmt_vid_out(file, fh, fmt); - - w = min(w, 720); - w = max(w, 2); - /* Why can the height be 576 even when the output is NTSC? - - Internally the buffers of the PVR350 are always set to 720x576. The - decoded video frame will always be placed in the top left corner of - this buffer. For any video which is not 720x576, the buffer will - then be cropped to remove the unused right and lower areas, with - the remaining image being scaled by the hardware to fit the display - area. The video can be scaled both up and down, so a 720x480 video - can be displayed full-screen on PAL and a 720x576 video can be - displayed without cropping on NTSC. - - Note that the scaling only occurs on the video stream, the osd - resolution is locked to the broadcast standard and not scaled. - - Thanks to Ian Armstrong for this explanation. */ - h = min(h, 576); - h = max(h, 2); - if (id->type == IVTV_DEC_STREAM_TYPE_YUV) - fmt->fmt.pix.field = field; - fmt->fmt.pix.width = w; - fmt->fmt.pix.height = h; - return ret; -} - -static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - u32 chromakey = fmt->fmt.win.chromakey; - u8 global_alpha = fmt->fmt.win.global_alpha; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - ivtv_g_fmt_vid_out_overlay(file, fh, fmt); - fmt->fmt.win.chromakey = chromakey; - fmt->fmt.win.global_alpha = global_alpha; - return 0; -} - -static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt) -{ - return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt); -} - -static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct v4l2_mbus_framefmt mbus_fmt; - int ret = ivtv_try_fmt_vid_cap(file, fh, fmt); - int w = fmt->fmt.pix.width; - int h = fmt->fmt.pix.height; - - if (ret) - return ret; - - if (itv->cxhdl.width == w && itv->cxhdl.height == h) - return 0; - - if (atomic_read(&itv->capturing) > 0) - return -EBUSY; - - itv->cxhdl.width = w; - itv->cxhdl.height = h; - if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) - fmt->fmt.pix.width /= 2; - mbus_fmt.width = fmt->fmt.pix.width; - mbus_fmt.height = h; - mbus_fmt.code = V4L2_MBUS_FMT_FIXED; - v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt); - return ivtv_g_fmt_vid_cap(file, fh, fmt); -} - -static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) - return -EBUSY; - itv->vbi.sliced_in->service_set = 0; - itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; - v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi); - return ivtv_g_fmt_vbi_cap(file, fh, fmt); -} - -static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced; - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt); - - if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI) - return ret; - - check_service_set(vbifmt, itv->is_50hz); - if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) - return -EBUSY; - itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt); - memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); - return 0; -} - -static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - int ret = ivtv_try_fmt_vid_out(file, fh, fmt); - - if (ret) - return ret; - - if (id->type != IVTV_DEC_STREAM_TYPE_YUV) - return 0; - - /* Return now if we already have some frame data */ - if (yi->stream_size) - return -EBUSY; - - yi->v4l2_src_w = fmt->fmt.pix.width; - yi->v4l2_src_h = fmt->fmt.pix.height; - - switch (fmt->fmt.pix.field) { - case V4L2_FIELD_NONE: - yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE; - break; - case V4L2_FIELD_ANY: - yi->lace_mode = IVTV_YUV_MODE_AUTO; - break; - case V4L2_FIELD_INTERLACED_BT: - yi->lace_mode = - IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD; - break; - case V4L2_FIELD_INTERLACED_TB: - default: - yi->lace_mode = IVTV_YUV_MODE_INTERLACED; - break; - } - yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1; - - if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) - itv->dma_data_req_size = - 1080 * ((yi->v4l2_src_h + 31) & ~31); - - return 0; -} - -static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt); - - if (ret == 0) { - itv->osd_chroma_key = fmt->fmt.win.chromakey; - itv->osd_global_alpha = fmt->fmt.win.global_alpha; - ivtv_set_osd_alpha(itv); - } - return ret; -} - -static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip) -{ - struct ivtv *itv = fh2id(fh)->itv; - - chip->ident = V4L2_IDENT_NONE; - chip->revision = 0; - if (chip->match.type == V4L2_CHIP_MATCH_HOST) { - if (v4l2_chip_match_host(&chip->match)) - chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; - return 0; - } - if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER && - chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR) - return -EINVAL; - /* TODO: is this correct? */ - return ivtv_call_all_err(itv, core, g_chip_ident, chip); -} - -#ifdef CONFIG_VIDEO_ADV_DEBUG -static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) -{ - struct v4l2_dbg_register *regs = arg; - volatile u8 __iomem *reg_start; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE) - reg_start = itv->reg_mem - IVTV_REG_OFFSET; - else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET && - regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE) - reg_start = itv->dec_mem - IVTV_DECODER_OFFSET; - else if (regs->reg < IVTV_ENCODER_SIZE) - reg_start = itv->enc_mem; - else - return -EINVAL; - - regs->size = 4; - if (cmd == VIDIOC_DBG_G_REGISTER) - regs->val = readl(regs->reg + reg_start); - else - writel(regs->val, regs->reg + reg_start); - return 0; -} - -static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (v4l2_chip_match_host(®->match)) - return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg); - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - ivtv_call_all(itv, core, g_register, reg); - return 0; -} - -static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (v4l2_chip_match_host(®->match)) - return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg); - /* TODO: subdev errors should not be ignored, this should become a - subdev helper function. */ - ivtv_call_all(itv, core, s_register, reg); - return 0; -} -#endif - -static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap) -{ - struct ivtv_open_id *id = fh2id(file->private_data); - struct ivtv *itv = id->itv; - struct ivtv_stream *s = &itv->streams[id->type]; - - strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver)); - strlcpy(vcap->card, itv->card_name, sizeof(vcap->card)); - snprintf(vcap->bus_info, sizeof(vcap->bus_info), "PCI:%s", pci_name(itv->pdev)); - vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS; - vcap->device_caps = s->caps; - return 0; -} - -static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin) -{ - struct ivtv *itv = fh2id(fh)->itv; - - return ivtv_get_audio_input(itv, vin->index, vin); -} - -static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin) -{ - struct ivtv *itv = fh2id(fh)->itv; - - vin->index = itv->audio_input; - return ivtv_get_audio_input(itv, vin->index, vin); -} - -static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (vout->index >= itv->nof_audio_inputs) - return -EINVAL; - - itv->audio_input = vout->index; - ivtv_audio_set_io(itv); - - return 0; -} - -static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin) -{ - struct ivtv *itv = fh2id(fh)->itv; - - /* set it to defaults from our table */ - return ivtv_get_audio_output(itv, vin->index, vin); -} - -static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin) -{ - struct ivtv *itv = fh2id(fh)->itv; - - vin->index = 0; - return ivtv_get_audio_output(itv, vin->index, vin); -} - -static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout) -{ - struct ivtv *itv = fh2id(fh)->itv; - - return ivtv_get_audio_output(itv, vout->index, vout); -} - -static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin) -{ - struct ivtv *itv = fh2id(fh)->itv; - - /* set it to defaults from our table */ - return ivtv_get_input(itv, vin->index, vin); -} - -static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout) -{ - struct ivtv *itv = fh2id(fh)->itv; - - return ivtv_get_output(itv, vout->index, vout); -} - -static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - int streamtype; - - streamtype = id->type; - - if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - cropcap->bounds.top = cropcap->bounds.left = 0; - cropcap->bounds.width = 720; - if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - cropcap->bounds.height = itv->is_50hz ? 576 : 480; - cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10; - cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11; - } else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { - if (yi->track_osd) { - cropcap->bounds.width = yi->osd_full_w; - cropcap->bounds.height = yi->osd_full_h; - } else { - cropcap->bounds.width = 720; - cropcap->bounds.height = - itv->is_out_50hz ? 576 : 480; - } - cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; - cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; - } else { - cropcap->bounds.height = itv->is_out_50hz ? 576 : 480; - cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10; - cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11; - } - cropcap->defrect = cropcap->bounds; - return 0; -} - -static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - int streamtype; - - streamtype = id->type; - - if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && - (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { - if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { - yi->main_rect = crop->c; - return 0; - } else { - if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, - crop->c.width, crop->c.height, crop->c.left, crop->c.top)) { - itv->main_rect = crop->c; - return 0; - } - } - return -EINVAL; - } - return -EINVAL; -} - -static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - int streamtype; - - streamtype = id->type; - - if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && - (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { - if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) - crop->c = yi->main_rect; - else - crop->c = itv->main_rect; - return 0; - } - return -EINVAL; -} - -static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, - { 0, 0, 0, 0 } - }, - { 1, 0, V4L2_FMT_FLAG_COMPRESSED, - "MPEG", V4L2_PIX_FMT_MPEG, - { 0, 0, 0, 0 } - } - }; - enum v4l2_buf_type type = fmt->type; - - if (fmt->index > 1) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - return 0; -} - -static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt) -{ - struct ivtv *itv = fh2id(fh)->itv; - - static struct v4l2_fmtdesc formats[] = { - { 0, 0, 0, - "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12, - { 0, 0, 0, 0 } - }, - { 1, 0, V4L2_FMT_FLAG_COMPRESSED, - "MPEG", V4L2_PIX_FMT_MPEG, - { 0, 0, 0, 0 } - } - }; - enum v4l2_buf_type type = fmt->type; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - - if (fmt->index > 1) - return -EINVAL; - - *fmt = formats[fmt->index]; - fmt->type = type; - - return 0; -} - -static int ivtv_g_input(struct file *file, void *fh, unsigned int *i) -{ - struct ivtv *itv = fh2id(fh)->itv; - - *i = itv->active_input; - - return 0; -} - -int ivtv_s_input(struct file *file, void *fh, unsigned int inp) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (inp < 0 || inp >= itv->nof_inputs) - return -EINVAL; - - if (inp == itv->active_input) { - IVTV_DEBUG_INFO("Input unchanged\n"); - return 0; - } - - if (atomic_read(&itv->capturing) > 0) { - return -EBUSY; - } - - IVTV_DEBUG_INFO("Changing input from %d to %d\n", - itv->active_input, inp); - - itv->active_input = inp; - /* Set the audio input to whatever is appropriate for the - input type. */ - itv->audio_input = itv->card->video_inputs[inp].audio_index; - - /* prevent others from messing with the streams until - we're finished changing inputs. */ - ivtv_mute(itv); - ivtv_video_set_io(itv); - ivtv_audio_set_io(itv); - ivtv_unmute(itv); - - return 0; -} - -static int ivtv_g_output(struct file *file, void *fh, unsigned int *i) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - - *i = itv->active_output; - - return 0; -} - -static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (outp >= itv->card->nof_outputs) - return -EINVAL; - - if (outp == itv->active_output) { - IVTV_DEBUG_INFO("Output unchanged\n"); - return 0; - } - IVTV_DEBUG_INFO("Changing output from %d to %d\n", - itv->active_output, outp); - - itv->active_output = outp; - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, - SAA7127_INPUT_TYPE_NORMAL, - itv->card->video_outputs[outp].video_output, 0); - - return 0; -} - -static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (vf->tuner != 0) - return -EINVAL; - - ivtv_call_all(itv, tuner, g_frequency, vf); - return 0; -} - -int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (vf->tuner != 0) - return -EINVAL; - - ivtv_mute(itv); - IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); - ivtv_call_all(itv, tuner, s_frequency, vf); - ivtv_unmute(itv); - return 0; -} - -static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std) -{ - struct ivtv *itv = fh2id(fh)->itv; - - *std = itv->std; - return 0; -} - -void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std) -{ - itv->std = *std; - itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; - itv->is_50hz = !itv->is_60hz; - cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz); - itv->cxhdl.width = 720; - itv->cxhdl.height = itv->is_50hz ? 576 : 480; - itv->vbi.count = itv->is_50hz ? 18 : 12; - itv->vbi.start[0] = itv->is_50hz ? 6 : 10; - itv->vbi.start[1] = itv->is_50hz ? 318 : 273; - - if (itv->hw_flags & IVTV_HW_CX25840) - itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; - - /* Tuner */ - ivtv_call_all(itv, core, s_std, itv->std); -} - -void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - DEFINE_WAIT(wait); - int f; - - /* set display standard */ - itv->std_out = *std; - itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0; - itv->is_out_50hz = !itv->is_out_60hz; - ivtv_call_all(itv, video, s_std_output, itv->std_out); - - /* - * The next firmware call is time sensitive. Time it to - * avoid risk of a hard lock, by trying to ensure the call - * happens within the first 100 lines of the top field. - * Make 4 attempts to sync to the decoder before giving up. - */ - mutex_unlock(&itv->serialize_lock); - for (f = 0; f < 4; f++) { - prepare_to_wait(&itv->vsync_waitq, &wait, - TASK_UNINTERRUPTIBLE); - if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100) - break; - schedule_timeout(msecs_to_jiffies(25)); - } - finish_wait(&itv->vsync_waitq, &wait); - mutex_lock(&itv->serialize_lock); - - if (f == 4) - IVTV_WARN("Mode change failed to sync to decoder\n"); - - ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); - itv->main_rect.left = 0; - itv->main_rect.top = 0; - itv->main_rect.width = 720; - itv->main_rect.height = itv->is_out_50hz ? 576 : 480; - ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4, - 720, itv->main_rect.height, 0, 0); - yi->main_rect = itv->main_rect; - if (!itv->osd_info) { - yi->osd_full_w = 720; - yi->osd_full_h = itv->is_out_50hz ? 576 : 480; - } -} - -int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if ((*std & V4L2_STD_ALL) == 0) - return -EINVAL; - - if (*std == itv->std) - return 0; - - if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) || - atomic_read(&itv->capturing) > 0 || - atomic_read(&itv->decoding) > 0) { - /* Switching standard would mess with already running - streams, prevent that by returning EBUSY. */ - return -EBUSY; - } - - IVTV_DEBUG_INFO("Switching standard to %llx.\n", - (unsigned long long)itv->std); - - ivtv_s_std_enc(itv, std); - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) - ivtv_s_std_dec(itv, std); - - return 0; -} - -static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - - if (vt->index != 0) - return -EINVAL; - - ivtv_call_all(itv, tuner, s_tuner, vt); - - return 0; -} - -static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (vt->index != 0) - return -EINVAL; - - ivtv_call_all(itv, tuner, g_tuner, vt); - - if (vt->type == V4L2_TUNER_RADIO) - strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); - else - strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name)); - return 0; -} - -static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap) -{ - struct ivtv *itv = fh2id(fh)->itv; - int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; - int f, l; - - if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) { - for (f = 0; f < 2; f++) { - for (l = 0; l < 24; l++) { - if (valid_service_line(f, l, itv->is_50hz)) - cap->service_lines[f][l] = set; - } - } - } else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { - if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT)) - return -EINVAL; - if (itv->is_60hz) { - cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525; - cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525; - } else { - cap->service_lines[0][23] = V4L2_SLICED_WSS_625; - cap->service_lines[0][16] = V4L2_SLICED_VPS; - } - } else { - return -EINVAL; - } - - set = 0; - for (f = 0; f < 2; f++) - for (l = 0; l < 24; l++) - set |= cap->service_lines[f][l]; - cap->service_set = set; - return 0; -} - -static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx) -{ - struct ivtv *itv = fh2id(fh)->itv; - struct v4l2_enc_idx_entry *e = idx->entry; - int entries; - int i; - - entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) % - IVTV_MAX_PGM_INDEX; - if (entries > V4L2_ENC_IDX_ENTRIES) - entries = V4L2_ENC_IDX_ENTRIES; - idx->entries = 0; - for (i = 0; i < entries; i++) { - *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX]; - if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) { - idx->entries++; - e++; - } - } - itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX; - return 0; -} - -static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - - - switch (enc->cmd) { - case V4L2_ENC_CMD_START: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); - enc->flags = 0; - return ivtv_start_capture(id); - - case V4L2_ENC_CMD_STOP: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); - enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; - ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END); - return 0; - - case V4L2_ENC_CMD_PAUSE: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); - enc->flags = 0; - - if (!atomic_read(&itv->capturing)) - return -EPERM; - if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) - return 0; - - ivtv_mute(itv); - ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0); - break; - - case V4L2_ENC_CMD_RESUME: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); - enc->flags = 0; - - if (!atomic_read(&itv->capturing)) - return -EPERM; - - if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags)) - return 0; - - ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1); - ivtv_unmute(itv); - break; - default: - IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); - return -EINVAL; - } - - return 0; -} - -static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc) -{ - struct ivtv *itv = fh2id(fh)->itv; - - switch (enc->cmd) { - case V4L2_ENC_CMD_START: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n"); - enc->flags = 0; - return 0; - - case V4L2_ENC_CMD_STOP: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n"); - enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END; - return 0; - - case V4L2_ENC_CMD_PAUSE: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n"); - enc->flags = 0; - return 0; - - case V4L2_ENC_CMD_RESUME: - IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n"); - enc->flags = 0; - return 0; - default: - IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd); - return -EINVAL; - } -} - -static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) -{ - struct ivtv *itv = fh2id(fh)->itv; - u32 data[CX2341X_MBOX_MAX_DATA]; - struct yuv_playback_info *yi = &itv->yuv_info; - - int pixfmt; - static u32 pixel_format[16] = { - V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */ - V4L2_PIX_FMT_RGB565, - V4L2_PIX_FMT_RGB555, - V4L2_PIX_FMT_RGB444, - V4L2_PIX_FMT_RGB32, - 0, - 0, - 0, - V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */ - V4L2_PIX_FMT_YUV565, - V4L2_PIX_FMT_YUV555, - V4L2_PIX_FMT_YUV444, - V4L2_PIX_FMT_YUV32, - 0, - 0, - 0, - }; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) - return -EINVAL; - if (!itv->osd_video_pbase) - return -EINVAL; - - fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY | - V4L2_FBUF_CAP_GLOBAL_ALPHA; - - ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); - data[0] |= (read_reg(0x2a00) >> 7) & 0x40; - pixfmt = (data[0] >> 3) & 0xf; - - fb->fmt.pixelformat = pixel_format[pixfmt]; - fb->fmt.width = itv->osd_rect.width; - fb->fmt.height = itv->osd_rect.height; - fb->fmt.field = V4L2_FIELD_INTERLACED; - fb->fmt.bytesperline = fb->fmt.width; - fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; - fb->fmt.field = V4L2_FIELD_INTERLACED; - fb->fmt.priv = 0; - if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8) - fb->fmt.bytesperline *= 2; - if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 || - fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32) - fb->fmt.bytesperline *= 2; - fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height; - fb->base = (void *)itv->osd_video_pbase; - fb->flags = 0; - - if (itv->osd_chroma_key_state) - fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY; - - if (itv->osd_global_alpha_state) - fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA; - - if (yi->track_osd) - fb->flags |= V4L2_FBUF_FLAG_OVERLAY; - - pixfmt &= 7; - - /* no local alpha for RGB565 or unknown formats */ - if (pixfmt == 1 || pixfmt > 4) - return 0; - - /* 16-bit formats have inverted local alpha */ - if (pixfmt == 2 || pixfmt == 3) - fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA; - else - fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA; - - if (itv->osd_local_alpha_state) { - /* 16-bit formats have inverted local alpha */ - if (pixfmt == 2 || pixfmt == 3) - fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA; - else - fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA; - } - - return 0; -} - -static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) - return -EINVAL; - if (!itv->osd_video_pbase) - return -EINVAL; - - itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; - itv->osd_local_alpha_state = - (fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0; - itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; - ivtv_set_osd_alpha(itv); - yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0; - return ivtv_g_fbuf(file, fh, fb); -} - -static int ivtv_overlay(struct file *file, void *fh, unsigned int on) -{ - struct ivtv_open_id *id = fh2id(fh); - struct ivtv *itv = id->itv; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY)) - return -EINVAL; - - ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0); - - return 0; -} - -static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub) -{ - switch (sub->type) { - case V4L2_EVENT_VSYNC: - case V4L2_EVENT_EOS: - return v4l2_event_subscribe(fh, sub, 0, NULL); - case V4L2_EVENT_CTRL: - return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops); - default: - return -EINVAL; - } -} - -static int ivtv_log_status(struct file *file, void *fh) -{ - struct ivtv *itv = fh2id(fh)->itv; - u32 data[CX2341X_MBOX_MAX_DATA]; - - int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT; - struct v4l2_input vidin; - struct v4l2_audio audin; - int i; - - IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); - if (itv->hw_flags & IVTV_HW_TVEEPROM) { - struct tveeprom tv; - - ivtv_read_eeprom(itv, &tv); - } - ivtv_call_all(itv, core, log_status); - ivtv_get_input(itv, itv->active_input, &vidin); - ivtv_get_audio_input(itv, itv->audio_input, &audin); - IVTV_INFO("Video Input: %s\n", vidin.name); - IVTV_INFO("Audio Input: %s%s\n", audin.name, - (itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : ""); - if (has_output) { - struct v4l2_output vidout; - struct v4l2_audioout audout; - int mode = itv->output_mode; - static const char * const output_modes[5] = { - "None", - "MPEG Streaming", - "YUV Streaming", - "YUV Frames", - "Passthrough", - }; - static const char * const alpha_mode[4] = { - "None", - "Global", - "Local", - "Global and Local" - }; - static const char * const pixel_format[16] = { - "ARGB Indexed", - "RGB 5:6:5", - "ARGB 1:5:5:5", - "ARGB 1:4:4:4", - "ARGB 8:8:8:8", - "5", - "6", - "7", - "AYUV Indexed", - "YUV 5:6:5", - "AYUV 1:5:5:5", - "AYUV 1:4:4:4", - "AYUV 8:8:8:8", - "13", - "14", - "15", - }; - - ivtv_get_output(itv, itv->active_output, &vidout); - ivtv_get_audio_output(itv, 0, &audout); - IVTV_INFO("Video Output: %s\n", vidout.name); - if (mode < 0 || mode > OUT_PASSTHROUGH) - mode = OUT_NONE; - IVTV_INFO("Output Mode: %s\n", output_modes[mode]); - ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0); - data[0] |= (read_reg(0x2a00) >> 7) & 0x40; - IVTV_INFO("Overlay: %s, Alpha: %s, Pixel Format: %s\n", - data[0] & 1 ? "On" : "Off", - alpha_mode[(data[0] >> 1) & 0x3], - pixel_format[(data[0] >> 3) & 0xf]); - } - IVTV_INFO("Tuner: %s\n", - test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); - v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, itv->v4l2_dev.name); - IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); - for (i = 0; i < IVTV_MAX_STREAMS; i++) { - struct ivtv_stream *s = &itv->streams[i]; - - if (s->vdev == NULL || s->buffers == 0) - continue; - IVTV_INFO("Stream %s: status 0x%04lx, %d%% of %d KiB (%d buffers) in use\n", s->name, s->s_flags, - (s->buffers - s->q_free.buffers) * 100 / s->buffers, - (s->buffers * s->buf_size) / 1024, s->buffers); - } - - IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", - (long long)itv->mpg_data_received, - (long long)itv->vbi_data_inserted); - return 0; -} - -static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) -{ - struct ivtv_open_id *id = fh2id(file->private_data); - struct ivtv *itv = id->itv; - - IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd); - return ivtv_video_command(itv, id, dec, false); -} - -static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec) -{ - struct ivtv_open_id *id = fh2id(file->private_data); - struct ivtv *itv = id->itv; - - IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd); - return ivtv_video_command(itv, id, dec, true); -} - -static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg) -{ - struct ivtv_open_id *id = fh2id(filp->private_data); - struct ivtv *itv = id->itv; - int nonblocking = filp->f_flags & O_NONBLOCK; - struct ivtv_stream *s = &itv->streams[id->type]; - unsigned long iarg = (unsigned long)arg; - - switch (cmd) { - case IVTV_IOC_DMA_FRAME: { - struct ivtv_dma_frame *args = arg; - - IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n"); - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) - return -EINVAL; - if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL) - return 0; - if (ivtv_start_decoding(id, id->type)) { - return -EBUSY; - } - if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) { - ivtv_release_stream(s); - return -EBUSY; - } - /* Mark that this file handle started the UDMA_YUV mode */ - id->yuv_frames = 1; - if (args->y_source == NULL) - return 0; - return ivtv_yuv_prep_frame(itv, args); - } - - case IVTV_IOC_PASSTHROUGH_MODE: - IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n"); - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - return ivtv_passthrough_mode(itv, *(int *)arg != 0); - - case VIDEO_GET_PTS: { - s64 *pts = arg; - s64 frame; - - IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n"); - if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { - *pts = s->dma_pts; - break; - } - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - return ivtv_g_pts_frame(itv, pts, &frame); - } - - case VIDEO_GET_FRAME_COUNT: { - s64 *frame = arg; - s64 pts; - - IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n"); - if (s->type < IVTV_DEC_STREAM_TYPE_MPG) { - *frame = 0; - break; - } - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - return ivtv_g_pts_frame(itv, &pts, frame); - } - - case VIDEO_PLAY: { - struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_PLAY\n"); - memset(&dc, 0, sizeof(dc)); - dc.cmd = V4L2_DEC_CMD_START; - return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_STOP: { - struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_STOP\n"); - memset(&dc, 0, sizeof(dc)); - dc.cmd = V4L2_DEC_CMD_STOP; - dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY; - return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_FREEZE: { - struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n"); - memset(&dc, 0, sizeof(dc)); - dc.cmd = V4L2_DEC_CMD_PAUSE; - return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_CONTINUE: { - struct v4l2_decoder_cmd dc; - - IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n"); - memset(&dc, 0, sizeof(dc)); - dc.cmd = V4L2_DEC_CMD_RESUME; - return ivtv_video_command(itv, id, &dc, 0); - } - - case VIDEO_COMMAND: - case VIDEO_TRY_COMMAND: { - /* Note: struct v4l2_decoder_cmd has the same layout as - struct video_command */ - struct v4l2_decoder_cmd *dc = arg; - int try = (cmd == VIDEO_TRY_COMMAND); - - if (try) - IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd); - else - IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd); - return ivtv_video_command(itv, id, dc, try); - } - - case VIDEO_GET_EVENT: { - struct video_event *ev = arg; - DEFINE_WAIT(wait); - - IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n"); - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - memset(ev, 0, sizeof(*ev)); - set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags); - - while (1) { - if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags)) - ev->type = VIDEO_EVENT_DECODER_STOPPED; - else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) { - ev->type = VIDEO_EVENT_VSYNC; - ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ? - VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN; - if (itv->output_mode == OUT_UDMA_YUV && - (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) == - IVTV_YUV_MODE_PROGRESSIVE) { - ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE; - } - } - if (ev->type) - return 0; - if (nonblocking) - return -EAGAIN; - /* Wait for event. Note that serialize_lock is locked, - so to allow other processes to access the driver while - we are waiting unlock first and later lock again. */ - mutex_unlock(&itv->serialize_lock); - prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE); - if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) && - !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) - schedule(); - finish_wait(&itv->event_waitq, &wait); - mutex_lock(&itv->serialize_lock); - if (signal_pending(current)) { - /* return if a signal was received */ - IVTV_DEBUG_INFO("User stopped wait for event\n"); - return -EINTR; - } - } - break; - } - - case VIDEO_SELECT_SOURCE: - IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n"); - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return -EINVAL; - return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX); - - case AUDIO_SET_MUTE: - IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n"); - itv->speed_mute_audio = iarg; - return 0; - - case AUDIO_CHANNEL_SELECT: - IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n"); - if (iarg > AUDIO_STEREO_SWAPPED) - return -EINVAL; - return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1); - - case AUDIO_BILINGUAL_CHANNEL_SELECT: - IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n"); - if (iarg > AUDIO_STEREO_SWAPPED) - return -EINVAL; - return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1); - - default: - return -EINVAL; - } - return 0; -} - -static long ivtv_default(struct file *file, void *fh, bool valid_prio, - int cmd, void *arg) -{ - struct ivtv *itv = fh2id(fh)->itv; - - if (!valid_prio) { - switch (cmd) { - case IVTV_IOC_PASSTHROUGH_MODE: - case VIDEO_PLAY: - case VIDEO_STOP: - case VIDEO_FREEZE: - case VIDEO_CONTINUE: - case VIDEO_COMMAND: - case VIDEO_SELECT_SOURCE: - case AUDIO_SET_MUTE: - case AUDIO_CHANNEL_SELECT: - case AUDIO_BILINGUAL_CHANNEL_SELECT: - return -EBUSY; - } - } - - switch (cmd) { - case VIDIOC_INT_RESET: { - u32 val = *(u32 *)arg; - - if ((val == 0 && itv->options.newi2c) || (val & 0x01)) - ivtv_reset_ir_gpio(itv); - if (val & 0x02) - v4l2_subdev_call(itv->sd_video, core, reset, 0); - break; - } - - case IVTV_IOC_DMA_FRAME: - case IVTV_IOC_PASSTHROUGH_MODE: - case VIDEO_GET_PTS: - case VIDEO_GET_FRAME_COUNT: - case VIDEO_GET_EVENT: - case VIDEO_PLAY: - case VIDEO_STOP: - case VIDEO_FREEZE: - case VIDEO_CONTINUE: - case VIDEO_COMMAND: - case VIDEO_TRY_COMMAND: - case VIDEO_SELECT_SOURCE: - case AUDIO_SET_MUTE: - case AUDIO_CHANNEL_SELECT: - case AUDIO_BILINGUAL_CHANNEL_SELECT: - return ivtv_decoder_ioctls(file, cmd, (void *)arg); - - default: - return -ENOTTY; - } - return 0; -} - -static const struct v4l2_ioctl_ops ivtv_ioctl_ops = { - .vidioc_querycap = ivtv_querycap, - .vidioc_s_audio = ivtv_s_audio, - .vidioc_g_audio = ivtv_g_audio, - .vidioc_enumaudio = ivtv_enumaudio, - .vidioc_s_audout = ivtv_s_audout, - .vidioc_g_audout = ivtv_g_audout, - .vidioc_enum_input = ivtv_enum_input, - .vidioc_enum_output = ivtv_enum_output, - .vidioc_enumaudout = ivtv_enumaudout, - .vidioc_cropcap = ivtv_cropcap, - .vidioc_s_crop = ivtv_s_crop, - .vidioc_g_crop = ivtv_g_crop, - .vidioc_g_input = ivtv_g_input, - .vidioc_s_input = ivtv_s_input, - .vidioc_g_output = ivtv_g_output, - .vidioc_s_output = ivtv_s_output, - .vidioc_g_frequency = ivtv_g_frequency, - .vidioc_s_frequency = ivtv_s_frequency, - .vidioc_s_tuner = ivtv_s_tuner, - .vidioc_g_tuner = ivtv_g_tuner, - .vidioc_g_enc_index = ivtv_g_enc_index, - .vidioc_g_fbuf = ivtv_g_fbuf, - .vidioc_s_fbuf = ivtv_s_fbuf, - .vidioc_g_std = ivtv_g_std, - .vidioc_s_std = ivtv_s_std, - .vidioc_overlay = ivtv_overlay, - .vidioc_log_status = ivtv_log_status, - .vidioc_enum_fmt_vid_cap = ivtv_enum_fmt_vid_cap, - .vidioc_encoder_cmd = ivtv_encoder_cmd, - .vidioc_try_encoder_cmd = ivtv_try_encoder_cmd, - .vidioc_decoder_cmd = ivtv_decoder_cmd, - .vidioc_try_decoder_cmd = ivtv_try_decoder_cmd, - .vidioc_enum_fmt_vid_out = ivtv_enum_fmt_vid_out, - .vidioc_g_fmt_vid_cap = ivtv_g_fmt_vid_cap, - .vidioc_g_fmt_vbi_cap = ivtv_g_fmt_vbi_cap, - .vidioc_g_fmt_sliced_vbi_cap = ivtv_g_fmt_sliced_vbi_cap, - .vidioc_g_fmt_vid_out = ivtv_g_fmt_vid_out, - .vidioc_g_fmt_vid_out_overlay = ivtv_g_fmt_vid_out_overlay, - .vidioc_g_fmt_sliced_vbi_out = ivtv_g_fmt_sliced_vbi_out, - .vidioc_s_fmt_vid_cap = ivtv_s_fmt_vid_cap, - .vidioc_s_fmt_vbi_cap = ivtv_s_fmt_vbi_cap, - .vidioc_s_fmt_sliced_vbi_cap = ivtv_s_fmt_sliced_vbi_cap, - .vidioc_s_fmt_vid_out = ivtv_s_fmt_vid_out, - .vidioc_s_fmt_vid_out_overlay = ivtv_s_fmt_vid_out_overlay, - .vidioc_s_fmt_sliced_vbi_out = ivtv_s_fmt_sliced_vbi_out, - .vidioc_try_fmt_vid_cap = ivtv_try_fmt_vid_cap, - .vidioc_try_fmt_vbi_cap = ivtv_try_fmt_vbi_cap, - .vidioc_try_fmt_sliced_vbi_cap = ivtv_try_fmt_sliced_vbi_cap, - .vidioc_try_fmt_vid_out = ivtv_try_fmt_vid_out, - .vidioc_try_fmt_vid_out_overlay = ivtv_try_fmt_vid_out_overlay, - .vidioc_try_fmt_sliced_vbi_out = ivtv_try_fmt_sliced_vbi_out, - .vidioc_g_sliced_vbi_cap = ivtv_g_sliced_vbi_cap, - .vidioc_g_chip_ident = ivtv_g_chip_ident, -#ifdef CONFIG_VIDEO_ADV_DEBUG - .vidioc_g_register = ivtv_g_register, - .vidioc_s_register = ivtv_s_register, -#endif - .vidioc_default = ivtv_default, - .vidioc_subscribe_event = ivtv_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -void ivtv_set_funcs(struct video_device *vdev) -{ - vdev->ioctl_ops = &ivtv_ioctl_ops; -} diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h deleted file mode 100644 index 7c553d16579b..000000000000 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - ioctl system call - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_IOCTL_H -#define IVTV_IOCTL_H - -u16 ivtv_service2vbi(int type); -void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); -u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt); -void ivtv_set_osd_alpha(struct ivtv *itv); -int ivtv_set_speed(struct ivtv *itv, int speed); -void ivtv_set_funcs(struct video_device *vdev); -void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std); -void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std); -int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf); -int ivtv_s_input(struct file *file, void *fh, unsigned int inp); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c deleted file mode 100644 index 1b3b9578bf47..000000000000 --- a/drivers/media/video/ivtv/ivtv-irq.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* interrupt handling - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-queue.h" -#include "ivtv-udma.h" -#include "ivtv-irq.h" -#include "ivtv-mailbox.h" -#include "ivtv-vbi.h" -#include "ivtv-yuv.h" -#include <media/v4l2-event.h> - -#define DMA_MAGIC_COOKIE 0x000001fe - -static void ivtv_dma_dec_start(struct ivtv_stream *s); - -static const int ivtv_stream_map[] = { - IVTV_ENC_STREAM_TYPE_MPG, - IVTV_ENC_STREAM_TYPE_YUV, - IVTV_ENC_STREAM_TYPE_PCM, - IVTV_ENC_STREAM_TYPE_VBI, -}; - - -static void ivtv_pio_work_handler(struct ivtv *itv) -{ - struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream]; - struct ivtv_buffer *buf; - int i = 0; - - IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n"); - if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS || - s->vdev == NULL || !ivtv_use_pio(s)) { - itv->cur_pio_stream = -1; - /* trigger PIO complete user interrupt */ - write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); - return; - } - IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name); - list_for_each_entry(buf, &s->q_dma.list, list) { - u32 size = s->sg_processing[i].size & 0x3ffff; - - /* Copy the data from the card to the buffer */ - if (s->type == IVTV_DEC_STREAM_TYPE_VBI) { - memcpy_fromio(buf->buf, itv->dec_mem + s->sg_processing[i].src - IVTV_DECODER_OFFSET, size); - } - else { - memcpy_fromio(buf->buf, itv->enc_mem + s->sg_processing[i].src, size); - } - i++; - if (i == s->sg_processing_size) - break; - } - write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44); -} - -void ivtv_irq_work_handler(struct kthread_work *work) -{ - struct ivtv *itv = container_of(work, struct ivtv, irq_work); - - if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags)) - ivtv_pio_work_handler(itv); - - if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags)) - ivtv_vbi_work_handler(itv); - - if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) - ivtv_yuv_work_handler(itv); -} - -/* Determine the required DMA size, setup enough buffers in the predma queue and - actually copy the data from the card to the buffers in case a PIO transfer is - required for this stream. - */ -static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MAX_DATA]) -{ - struct ivtv *itv = s->itv; - struct ivtv_buffer *buf; - u32 bytes_needed = 0; - u32 offset, size; - u32 UVoffset = 0, UVsize = 0; - int skip_bufs = s->q_predma.buffers; - int idx = s->sg_pending_size; - int rc; - - /* sanity checks */ - if (s->vdev == NULL) { - IVTV_DEBUG_WARN("Stream %s not started\n", s->name); - return -1; - } - if (!test_bit(IVTV_F_S_CLAIMED, &s->s_flags)) { - IVTV_DEBUG_WARN("Stream %s not open\n", s->name); - return -1; - } - - /* determine offset, size and PTS for the various streams */ - switch (s->type) { - case IVTV_ENC_STREAM_TYPE_MPG: - offset = data[1]; - size = data[2]; - s->pending_pts = 0; - break; - - case IVTV_ENC_STREAM_TYPE_YUV: - offset = data[1]; - size = data[2]; - UVoffset = data[3]; - UVsize = data[4]; - s->pending_pts = ((u64) data[5] << 32) | data[6]; - break; - - case IVTV_ENC_STREAM_TYPE_PCM: - offset = data[1] + 12; - size = data[2] - 12; - s->pending_pts = read_dec(offset - 8) | - ((u64)(read_dec(offset - 12)) << 32); - if (itv->has_cx23415) - offset += IVTV_DECODER_OFFSET; - break; - - case IVTV_ENC_STREAM_TYPE_VBI: - size = itv->vbi.enc_size * itv->vbi.fpi; - offset = read_enc(itv->vbi.enc_start - 4) + 12; - if (offset == 12) { - IVTV_DEBUG_INFO("VBI offset == 0\n"); - return -1; - } - s->pending_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32); - break; - - case IVTV_DEC_STREAM_TYPE_VBI: - size = read_dec(itv->vbi.dec_start + 4) + 8; - offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start; - s->pending_pts = 0; - offset += IVTV_DECODER_OFFSET; - break; - default: - /* shouldn't happen */ - return -1; - } - - /* if this is the start of the DMA then fill in the magic cookie */ - if (s->sg_pending_size == 0 && ivtv_use_dma(s)) { - if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM || - s->type == IVTV_DEC_STREAM_TYPE_VBI)) { - s->pending_backup = read_dec(offset - IVTV_DECODER_OFFSET); - write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET); - } - else { - s->pending_backup = read_enc(offset); - write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset); - } - s->pending_offset = offset; - } - - bytes_needed = size; - if (s->type == IVTV_ENC_STREAM_TYPE_YUV) { - /* The size for the Y samples needs to be rounded upwards to a - multiple of the buf_size. The UV samples then start in the - next buffer. */ - bytes_needed = s->buf_size * ((bytes_needed + s->buf_size - 1) / s->buf_size); - bytes_needed += UVsize; - } - - IVTV_DEBUG_HI_DMA("%s %s: 0x%08x bytes at 0x%08x\n", - ivtv_use_pio(s) ? "PIO" : "DMA", s->name, bytes_needed, offset); - - rc = ivtv_queue_move(s, &s->q_free, &s->q_full, &s->q_predma, bytes_needed); - if (rc < 0) { /* Insufficient buffers */ - IVTV_DEBUG_WARN("Cannot obtain %d bytes for %s data transfer\n", - bytes_needed, s->name); - return -1; - } - if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) { - IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name); - IVTV_WARN("Cause: the application is not reading fast enough.\n"); - } - s->buffers_stolen = rc; - - /* got the buffers, now fill in sg_pending */ - buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); - memset(buf->buf, 0, 128); - list_for_each_entry(buf, &s->q_predma.list, list) { - if (skip_bufs-- > 0) - continue; - s->sg_pending[idx].dst = buf->dma_handle; - s->sg_pending[idx].src = offset; - s->sg_pending[idx].size = s->buf_size; - buf->bytesused = min(size, s->buf_size); - buf->dma_xfer_cnt = s->dma_xfer_cnt; - - s->q_predma.bytesused += buf->bytesused; - size -= buf->bytesused; - offset += s->buf_size; - - /* Sync SG buffers */ - ivtv_buf_sync_for_device(s, buf); - - if (size == 0) { /* YUV */ - /* process the UV section */ - offset = UVoffset; - size = UVsize; - } - idx++; - } - s->sg_pending_size = idx; - return 0; -} - -static void dma_post(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - struct ivtv_buffer *buf = NULL; - struct list_head *p; - u32 offset; - __le32 *u32buf; - int x = 0; - - IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", - s->name, s->dma_offset); - list_for_each(p, &s->q_dma.list) { - buf = list_entry(p, struct ivtv_buffer, list); - u32buf = (__le32 *)buf->buf; - - /* Sync Buffer */ - ivtv_buf_sync_for_cpu(s, buf); - - if (x == 0 && ivtv_use_dma(s)) { - offset = s->dma_last_offset; - if (u32buf[offset / 4] != DMA_MAGIC_COOKIE) - { - for (offset = 0; offset < 64; offset++) { - if (u32buf[offset] == DMA_MAGIC_COOKIE) { - break; - } - } - offset *= 4; - if (offset == 256) { - IVTV_DEBUG_WARN("%s: Couldn't find start of buffer within the first 256 bytes\n", s->name); - offset = s->dma_last_offset; - } - if (s->dma_last_offset != offset) - IVTV_DEBUG_WARN("%s: offset %d -> %d\n", s->name, s->dma_last_offset, offset); - s->dma_last_offset = offset; - } - if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM || - s->type == IVTV_DEC_STREAM_TYPE_VBI)) { - write_dec_sync(0, s->dma_offset - IVTV_DECODER_OFFSET); - } - else { - write_enc_sync(0, s->dma_offset); - } - if (offset) { - buf->bytesused -= offset; - memcpy(buf->buf, buf->buf + offset, buf->bytesused + offset); - } - *u32buf = cpu_to_le32(s->dma_backup); - } - x++; - /* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */ - if (s->type == IVTV_ENC_STREAM_TYPE_MPG || - s->type == IVTV_ENC_STREAM_TYPE_VBI) - buf->b_flags |= IVTV_F_B_NEED_BUF_SWAP; - } - if (buf) - buf->bytesused += s->dma_last_offset; - if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { - list_for_each_entry(buf, &s->q_dma.list, list) { - /* Parse and Groom VBI Data */ - s->q_dma.bytesused -= buf->bytesused; - ivtv_process_vbi_data(itv, buf, 0, s->type); - s->q_dma.bytesused += buf->bytesused; - } - if (s->fh == NULL) { - ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); - return; - } - } - ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused); - if (s->fh) - wake_up(&s->waitq); -} - -void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock) -{ - struct ivtv *itv = s->itv; - struct yuv_playback_info *yi = &itv->yuv_info; - u8 frame = yi->draw_frame; - struct yuv_frame_info *f = &yi->new_frame_info[frame]; - struct ivtv_buffer *buf; - u32 y_size = 720 * ((f->src_h + 31) & ~31); - u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET; - int y_done = 0; - int bytes_written = 0; - unsigned long flags = 0; - int idx = 0; - - IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset); - - /* Insert buffer block for YUV if needed */ - if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) { - if (yi->blanking_dmaptr) { - s->sg_pending[idx].src = yi->blanking_dmaptr; - s->sg_pending[idx].dst = offset; - s->sg_pending[idx].size = 720 * 16; - } - offset += 720 * 16; - idx++; - } - - list_for_each_entry(buf, &s->q_predma.list, list) { - /* YUV UV Offset from Y Buffer */ - if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done && - (bytes_written + buf->bytesused) >= y_size) { - s->sg_pending[idx].src = buf->dma_handle; - s->sg_pending[idx].dst = offset; - s->sg_pending[idx].size = y_size - bytes_written; - offset = uv_offset; - if (s->sg_pending[idx].size != buf->bytesused) { - idx++; - s->sg_pending[idx].src = - buf->dma_handle + s->sg_pending[idx - 1].size; - s->sg_pending[idx].dst = offset; - s->sg_pending[idx].size = - buf->bytesused - s->sg_pending[idx - 1].size; - offset += s->sg_pending[idx].size; - } - y_done = 1; - } else { - s->sg_pending[idx].src = buf->dma_handle; - s->sg_pending[idx].dst = offset; - s->sg_pending[idx].size = buf->bytesused; - offset += buf->bytesused; - } - bytes_written += buf->bytesused; - - /* Sync SG buffers */ - ivtv_buf_sync_for_device(s, buf); - idx++; - } - s->sg_pending_size = idx; - - /* Sync Hardware SG List of buffers */ - ivtv_stream_sync_for_device(s); - if (lock) - spin_lock_irqsave(&itv->dma_reg_lock, flags); - if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) { - ivtv_dma_dec_start(s); - } - else { - set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); - } - if (lock) - spin_unlock_irqrestore(&itv->dma_reg_lock, flags); -} - -static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - - s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src); - s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst); - s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000); - s->sg_processed++; - /* Sync Hardware SG List of buffers */ - ivtv_stream_sync_for_device(s); - write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR); - write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); - itv->dma_timer.expires = jiffies + msecs_to_jiffies(300); - add_timer(&itv->dma_timer); -} - -static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - - s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src); - s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst); - s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000); - s->sg_processed++; - /* Sync Hardware SG List of buffers */ - ivtv_stream_sync_for_device(s); - write_reg(s->sg_handle, IVTV_REG_DECDMAADDR); - write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); - itv->dma_timer.expires = jiffies + msecs_to_jiffies(300); - add_timer(&itv->dma_timer); -} - -/* start the encoder DMA */ -static void ivtv_dma_enc_start(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - int i; - - IVTV_DEBUG_HI_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name); - - if (s->q_predma.bytesused) - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - - if (ivtv_use_dma(s)) - s->sg_pending[s->sg_pending_size - 1].size += 256; - - /* If this is an MPEG stream, and VBI data is also pending, then append the - VBI DMA to the MPEG DMA and transfer both sets of data at once. - - VBI DMA is a second class citizen compared to MPEG and mixing them together - will confuse the firmware (the end of a VBI DMA is seen as the end of a - MPEG DMA, thus effectively dropping an MPEG frame). So instead we make - sure we only use the MPEG DMA to transfer the VBI DMA if both are in - use. This way no conflicts occur. */ - clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); - if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->sg_pending_size && - s->sg_pending_size + s_vbi->sg_pending_size <= s->buffers) { - ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); - if (ivtv_use_dma(s_vbi)) - s_vbi->sg_pending[s_vbi->sg_pending_size - 1].size += 256; - for (i = 0; i < s_vbi->sg_pending_size; i++) { - s->sg_pending[s->sg_pending_size++] = s_vbi->sg_pending[i]; - } - s_vbi->dma_offset = s_vbi->pending_offset; - s_vbi->sg_pending_size = 0; - s_vbi->dma_xfer_cnt++; - set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags); - IVTV_DEBUG_HI_DMA("include DMA for %s\n", s_vbi->name); - } - - s->dma_xfer_cnt++; - memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size); - s->sg_processing_size = s->sg_pending_size; - s->sg_pending_size = 0; - s->sg_processed = 0; - s->dma_offset = s->pending_offset; - s->dma_backup = s->pending_backup; - s->dma_pts = s->pending_pts; - - if (ivtv_use_pio(s)) { - set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags); - set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); - set_bit(IVTV_F_I_PIO, &itv->i_flags); - itv->cur_pio_stream = s->type; - } - else { - itv->dma_retries = 0; - ivtv_dma_enc_start_xfer(s); - set_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = s->type; - } -} - -static void ivtv_dma_dec_start(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - - if (s->q_predma.bytesused) - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); - s->dma_xfer_cnt++; - memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size); - s->sg_processing_size = s->sg_pending_size; - s->sg_pending_size = 0; - s->sg_processed = 0; - - IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name); - itv->dma_retries = 0; - ivtv_dma_dec_start_xfer(s); - set_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = s->type; -} - -static void ivtv_irq_dma_read(struct ivtv *itv) -{ - struct ivtv_stream *s = NULL; - struct ivtv_buffer *buf; - int hw_stream_type = 0; - - IVTV_DEBUG_HI_IRQ("DEC DMA READ\n"); - - del_timer(&itv->dma_timer); - - if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0) - return; - - if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { - s = &itv->streams[itv->cur_dma_stream]; - ivtv_stream_sync_for_cpu(s); - - if (read_reg(IVTV_REG_DMASTATUS) & 0x14) { - IVTV_DEBUG_WARN("DEC DMA ERROR %x (xfer %d of %d, retry %d)\n", - read_reg(IVTV_REG_DMASTATUS), - s->sg_processed, s->sg_processing_size, itv->dma_retries); - write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); - if (itv->dma_retries == 3) { - /* Too many retries, give up on this frame */ - itv->dma_retries = 0; - s->sg_processed = s->sg_processing_size; - } - else { - /* Retry, starting with the first xfer segment. - Just retrying the current segment is not sufficient. */ - s->sg_processed = 0; - itv->dma_retries++; - } - } - if (s->sg_processed < s->sg_processing_size) { - /* DMA next buffer */ - ivtv_dma_dec_start_xfer(s); - return; - } - if (s->type == IVTV_DEC_STREAM_TYPE_YUV) - hw_stream_type = 2; - IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused); - - /* For some reason must kick the firmware, like PIO mode, - I think this tells the firmware we are done and the size - of the xfer so it can calculate what we need next. - I think we can do this part ourselves but would have to - fully calculate xfer info ourselves and not use interrupts - */ - ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, s->q_dma.bytesused, - hw_stream_type); - - /* Free last DMA call */ - while ((buf = ivtv_dequeue(s, &s->q_dma)) != NULL) { - ivtv_buf_sync_for_cpu(s, buf); - ivtv_enqueue(s, buf, &s->q_free); - } - wake_up(&s->waitq); - } - clear_bit(IVTV_F_I_UDMA, &itv->i_flags); - clear_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = -1; - wake_up(&itv->dma_waitq); -} - -static void ivtv_irq_enc_dma_complete(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv_stream *s; - - ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); - IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream); - - del_timer(&itv->dma_timer); - - if (itv->cur_dma_stream < 0) - return; - - s = &itv->streams[itv->cur_dma_stream]; - ivtv_stream_sync_for_cpu(s); - - if (data[0] & 0x18) { - IVTV_DEBUG_WARN("ENC DMA ERROR %x (offset %08x, xfer %d of %d, retry %d)\n", data[0], - s->dma_offset, s->sg_processed, s->sg_processing_size, itv->dma_retries); - write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); - if (itv->dma_retries == 3) { - /* Too many retries, give up on this frame */ - itv->dma_retries = 0; - s->sg_processed = s->sg_processing_size; - } - else { - /* Retry, starting with the first xfer segment. - Just retrying the current segment is not sufficient. */ - s->sg_processed = 0; - itv->dma_retries++; - } - } - if (s->sg_processed < s->sg_processing_size) { - /* DMA next buffer */ - ivtv_dma_enc_start_xfer(s); - return; - } - clear_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = -1; - dma_post(s); - if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { - s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - dma_post(s); - } - s->sg_processing_size = 0; - s->sg_processed = 0; - wake_up(&itv->dma_waitq); -} - -static void ivtv_irq_enc_pio_complete(struct ivtv *itv) -{ - struct ivtv_stream *s; - - if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) { - itv->cur_pio_stream = -1; - return; - } - s = &itv->streams[itv->cur_pio_stream]; - IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name); - clear_bit(IVTV_F_I_PIO, &itv->i_flags); - itv->cur_pio_stream = -1; - dma_post(s); - if (s->type == IVTV_ENC_STREAM_TYPE_MPG) - ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0); - else if (s->type == IVTV_ENC_STREAM_TYPE_YUV) - ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1); - else if (s->type == IVTV_ENC_STREAM_TYPE_PCM) - ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2); - clear_bit(IVTV_F_I_PIO, &itv->i_flags); - if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) { - s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - dma_post(s); - } - wake_up(&itv->dma_waitq); -} - -static void ivtv_irq_dma_err(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - u32 status; - - del_timer(&itv->dma_timer); - - ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data); - status = read_reg(IVTV_REG_DMASTATUS); - IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1], - status, itv->cur_dma_stream); - /* - * We do *not* write back to the IVTV_REG_DMASTATUS register to - * clear the error status, if either the encoder write (0x02) or - * decoder read (0x01) bus master DMA operation do not indicate - * completed. We can race with the DMA engine, which may have - * transitioned to completed status *after* we read the register. - * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the - * DMA engine has completed, will cause the DMA engine to stop working. - */ - status &= 0x3; - if (status == 0x3) - write_reg(status, IVTV_REG_DMASTATUS); - - if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && - itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) { - struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream]; - - if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { - /* retry */ - /* - * FIXME - handle cases of DMA error similar to - * encoder below, except conditioned on status & 0x1 - */ - ivtv_dma_dec_start(s); - return; - } else { - if ((status & 0x2) == 0) { - /* - * CX2341x Bus Master DMA write is ongoing. - * Reset the timer and let it complete. - */ - itv->dma_timer.expires = - jiffies + msecs_to_jiffies(600); - add_timer(&itv->dma_timer); - return; - } - - if (itv->dma_retries < 3) { - /* - * CX2341x Bus Master DMA write has ended. - * Retry the write, starting with the first - * xfer segment. Just retrying the current - * segment is not sufficient. - */ - s->sg_processed = 0; - itv->dma_retries++; - ivtv_dma_enc_start_xfer(s); - return; - } - /* Too many retries, give up on this one */ - } - - } - if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { - ivtv_udma_start(itv); - return; - } - clear_bit(IVTV_F_I_UDMA, &itv->i_flags); - clear_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = -1; - wake_up(&itv->dma_waitq); -} - -static void ivtv_irq_enc_start_cap(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv_stream *s; - - /* Get DMA destination and size arguments from card */ - ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data); - IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]); - - if (data[0] > 2 || data[1] == 0 || data[2] == 0) { - IVTV_DEBUG_WARN("Unknown input: %08x %08x %08x\n", - data[0], data[1], data[2]); - return; - } - s = &itv->streams[ivtv_stream_map[data[0]]]; - if (!stream_enc_dma_append(s, data)) { - set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); - } -} - -static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv_stream *s; - - IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n"); - s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; - - if (!stream_enc_dma_append(s, data)) - set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags); -} - -static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; - - IVTV_DEBUG_HI_IRQ("DEC VBI REINSERT\n"); - if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && - !stream_enc_dma_append(s, data)) { - set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags); - } -} - -static void ivtv_irq_dec_data_req(struct ivtv *itv) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv_stream *s; - - /* YUV or MPG */ - - if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) { - ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data); - itv->dma_data_req_size = - 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31); - itv->dma_data_req_offset = data[1]; - if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0) - ivtv_yuv_frame_complete(itv); - s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; - } - else { - ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data); - itv->dma_data_req_size = min_t(u32, data[2], 0x10000); - itv->dma_data_req_offset = data[1]; - s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG]; - } - IVTV_DEBUG_HI_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused, - itv->dma_data_req_offset, itv->dma_data_req_size); - if (itv->dma_data_req_size == 0 || s->q_full.bytesused < itv->dma_data_req_size) { - set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); - } - else { - if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) - ivtv_yuv_setup_stream_frame(itv); - clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); - ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size); - ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0); - } -} - -static void ivtv_irq_vsync(struct ivtv *itv) -{ - /* The vsync interrupt is unusual in that it won't clear until - * the end of the first line for the current field, at which - * point it clears itself. This can result in repeated vsync - * interrupts, or a missed vsync. Read some of the registers - * to determine the line being displayed and ensure we handle - * one vsync per frame. - */ - unsigned int frame = read_reg(IVTV_REG_DEC_LINE_FIELD) & 1; - struct yuv_playback_info *yi = &itv->yuv_info; - int last_dma_frame = atomic_read(&yi->next_dma_frame); - struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame]; - - if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n"); - - if (((frame ^ f->sync_field) == 0 && - ((itv->last_vsync_field & 1) ^ f->sync_field)) || - (frame != (itv->last_vsync_field & 1) && !f->interlaced)) { - int next_dma_frame = last_dma_frame; - - if (!(f->interlaced && f->delay && yi->fields_lapsed < 1)) { - if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) { - write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c); - write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830); - write_reg(yuv_offset[next_dma_frame] >> 4, 0x834); - write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838); - next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS; - atomic_set(&yi->next_dma_frame, next_dma_frame); - yi->fields_lapsed = -1; - yi->running = 1; - } - } - } - if (frame != (itv->last_vsync_field & 1)) { - static const struct v4l2_event evtop = { - .type = V4L2_EVENT_VSYNC, - .u.vsync.field = V4L2_FIELD_TOP, - }; - static const struct v4l2_event evbottom = { - .type = V4L2_EVENT_VSYNC, - .u.vsync.field = V4L2_FIELD_BOTTOM, - }; - struct ivtv_stream *s = ivtv_get_output_stream(itv); - - itv->last_vsync_field += 1; - if (frame == 0) { - clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags); - clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags); - } - else { - set_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags); - } - if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) { - set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags); - wake_up(&itv->event_waitq); - if (s) - wake_up(&s->waitq); - } - if (s && s->vdev) - v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom); - wake_up(&itv->vsync_waitq); - - /* Send VBI to saa7127 */ - if (frame && (itv->output_mode == OUT_PASSTHROUGH || - test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) || - test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) || - test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) { - set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); - set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); - } - - /* Check if we need to update the yuv registers */ - if (yi->running && (yi->yuv_forced_update || f->update)) { - if (!f->update) { - last_dma_frame = - (u8)(atomic_read(&yi->next_dma_frame) - - 1) % IVTV_YUV_BUFFERS; - f = &yi->new_frame_info[last_dma_frame]; - } - - if (f->src_w) { - yi->update_frame = last_dma_frame; - f->update = 0; - yi->yuv_forced_update = 0; - set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); - set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags); - } - } - - yi->fields_lapsed++; - } -} - -#define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT) - -irqreturn_t ivtv_irq_handler(int irq, void *dev_id) -{ - struct ivtv *itv = (struct ivtv *)dev_id; - u32 combo; - u32 stat; - int i; - u8 vsync_force = 0; - - spin_lock(&itv->dma_reg_lock); - /* get contents of irq status register */ - stat = read_reg(IVTV_REG_IRQSTATUS); - - combo = ~itv->irqmask & stat; - - /* Clear out IRQ */ - if (combo) write_reg(combo, IVTV_REG_IRQSTATUS); - - if (0 == combo) { - /* The vsync interrupt is unusual and clears itself. If we - * took too long, we may have missed it. Do some checks - */ - if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { - /* vsync is enabled, see if we're in a new field */ - if ((itv->last_vsync_field & 1) != - (read_reg(IVTV_REG_DEC_LINE_FIELD) & 1)) { - /* New field, looks like we missed it */ - IVTV_DEBUG_YUV("VSync interrupt missed %d\n", - read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16); - vsync_force = 1; - } - } - - if (!vsync_force) { - /* No Vsync expected, wasn't for us */ - spin_unlock(&itv->dma_reg_lock); - return IRQ_NONE; - } - } - - /* Exclude interrupts noted below from the output, otherwise the log is flooded with - these messages */ - if (combo & ~0xff6d0400) - IVTV_DEBUG_HI_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo); - - if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) { - IVTV_DEBUG_HI_IRQ("DEC DMA COMPLETE\n"); - } - - if (combo & IVTV_IRQ_DMA_READ) { - ivtv_irq_dma_read(itv); - } - - if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) { - ivtv_irq_enc_dma_complete(itv); - } - - if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) { - ivtv_irq_enc_pio_complete(itv); - } - - if (combo & IVTV_IRQ_DMA_ERR) { - ivtv_irq_dma_err(itv); - } - - if (combo & IVTV_IRQ_ENC_START_CAP) { - ivtv_irq_enc_start_cap(itv); - } - - if (combo & IVTV_IRQ_ENC_VBI_CAP) { - ivtv_irq_enc_vbi_cap(itv); - } - - if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { - ivtv_irq_dec_vbi_reinsert(itv); - } - - if (combo & IVTV_IRQ_ENC_EOS) { - IVTV_DEBUG_IRQ("ENC EOS\n"); - set_bit(IVTV_F_I_EOS, &itv->i_flags); - wake_up(&itv->eos_waitq); - } - - if (combo & IVTV_IRQ_DEC_DATA_REQ) { - ivtv_irq_dec_data_req(itv); - } - - /* Decoder Vertical Sync - We can't rely on 'combo', so check if vsync enabled */ - if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) { - ivtv_irq_vsync(itv); - } - - if (combo & IVTV_IRQ_ENC_VIM_RST) { - IVTV_DEBUG_IRQ("VIM RST\n"); - /*ivtv_vapi(itv, CX2341X_ENC_REFRESH_INPUT, 0); */ - } - - if (combo & IVTV_IRQ_DEC_AUD_MODE_CHG) { - IVTV_DEBUG_INFO("Stereo mode changed\n"); - } - - if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) { - itv->irq_rr_idx++; - for (i = 0; i < IVTV_MAX_STREAMS; i++) { - int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS; - struct ivtv_stream *s = &itv->streams[idx]; - - if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) - continue; - if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) - ivtv_dma_dec_start(s); - else - ivtv_dma_enc_start(s); - break; - } - - if (i == IVTV_MAX_STREAMS && - test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) - ivtv_udma_start(itv); - } - - if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) { - itv->irq_rr_idx++; - for (i = 0; i < IVTV_MAX_STREAMS; i++) { - int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS; - struct ivtv_stream *s = &itv->streams[idx]; - - if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags)) - continue; - if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG) - ivtv_dma_enc_start(s); - break; - } - } - - if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) { - queue_kthread_work(&itv->irq_worker, &itv->irq_work); - } - - spin_unlock(&itv->dma_reg_lock); - - /* If we've just handled a 'forced' vsync, it's safest to say it - * wasn't ours. Another device may have triggered it at just - * the right time. - */ - return vsync_force ? IRQ_NONE : IRQ_HANDLED; -} - -void ivtv_unfinished_dma(unsigned long arg) -{ - struct ivtv *itv = (struct ivtv *)arg; - - if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) - return; - IVTV_ERR("DMA TIMEOUT %08x %d\n", read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream); - - write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS); - clear_bit(IVTV_F_I_UDMA, &itv->i_flags); - clear_bit(IVTV_F_I_DMA, &itv->i_flags); - itv->cur_dma_stream = -1; - wake_up(&itv->dma_waitq); -} diff --git a/drivers/media/video/ivtv/ivtv-irq.h b/drivers/media/video/ivtv/ivtv-irq.h deleted file mode 100644 index 1e84433737cc..000000000000 --- a/drivers/media/video/ivtv/ivtv-irq.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - interrupt handling - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_IRQ_H -#define IVTV_IRQ_H - -#define IVTV_IRQ_ENC_START_CAP (0x1 << 31) -#define IVTV_IRQ_ENC_EOS (0x1 << 30) -#define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) -#define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) -#define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) -#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25) -#define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) -#define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) -#define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) -#define IVTV_IRQ_DEC_VBI_RE_INSERT (0x1 << 19) -#define IVTV_IRQ_DMA_ERR (0x1 << 18) -#define IVTV_IRQ_DMA_WRITE (0x1 << 17) -#define IVTV_IRQ_DMA_READ (0x1 << 16) -#define IVTV_IRQ_DEC_VSYNC (0x1 << 10) - -/* IRQ Masks */ -#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\ - IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE) - -#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) -#define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) - -irqreturn_t ivtv_irq_handler(int irq, void *dev_id); - -void ivtv_irq_work_handler(struct kthread_work *work); -void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock); -void ivtv_unfinished_dma(unsigned long arg); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c deleted file mode 100644 index e3ce96763785..000000000000 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - mailbox functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdarg.h> - -#include "ivtv-driver.h" -#include "ivtv-mailbox.h" - -/* Firmware mailbox flags*/ -#define IVTV_MBOX_FIRMWARE_DONE 0x00000004 -#define IVTV_MBOX_DRIVER_DONE 0x00000002 -#define IVTV_MBOX_DRIVER_BUSY 0x00000001 -#define IVTV_MBOX_FREE 0x00000000 - -/* Firmware mailbox standard timeout */ -#define IVTV_API_STD_TIMEOUT 0x02000000 - -#define API_CACHE (1 << 0) /* Allow the command to be stored in the cache */ -#define API_RESULT (1 << 1) /* Allow 1 second for this cmd to end */ -#define API_FAST_RESULT (3 << 1) /* Allow 0.1 second for this cmd to end */ -#define API_DMA (1 << 3) /* DMA mailbox, has special handling */ -#define API_HIGH_VOL (1 << 5) /* High volume command (i.e. called during encoding or decoding) */ -#define API_NO_WAIT_MB (1 << 4) /* Command may not wait for a free mailbox */ -#define API_NO_WAIT_RES (1 << 5) /* Command may not wait for the result */ -#define API_NO_POLL (1 << 6) /* Avoid pointless polling */ - -struct ivtv_api_info { - int flags; /* Flags, see above */ - const char *name; /* The name of the command */ -}; - -#define API_ENTRY(x, f) [x] = { (f), #x } - -static const struct ivtv_api_info api_info[256] = { - /* MPEG encoder API */ - API_ENTRY(CX2341X_ENC_PING_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_START_CAPTURE, API_RESULT | API_NO_POLL), - API_ENTRY(CX2341X_ENC_STOP_CAPTURE, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_AUDIO_ID, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_VIDEO_ID, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_PCR_ID, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_FRAME_RATE, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_FRAME_SIZE, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_BIT_RATE, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_GOP_PROPERTIES, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_ASPECT_RATIO, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_MODE, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_PROPS, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_CORING_LEVELS, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_VBI_LINE, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_STREAM_TYPE, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_OUTPUT_PORT, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_AUDIO_PROPERTIES, API_CACHE), - API_ENTRY(CX2341X_ENC_HALT_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_GET_VERSION, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_SET_GOP_CLOSURE, API_CACHE), - API_ENTRY(CX2341X_ENC_GET_SEQ_END, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_PGM_INDEX_INFO, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_SET_VBI_CONFIG, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE, API_CACHE), - API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST, API_DMA | API_HIGH_VOL), - API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE, API_CACHE), - API_ENTRY(CX2341X_ENC_PAUSE_ENCODER, API_RESULT), - API_ENTRY(CX2341X_ENC_REFRESH_INPUT, API_NO_WAIT_MB | API_HIGH_VOL), - API_ENTRY(CX2341X_ENC_SET_COPYRIGHT, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES, API_CACHE), - API_ENTRY(CX2341X_ENC_SET_PLACEHOLDER, API_CACHE), - API_ENTRY(CX2341X_ENC_MUTE_VIDEO, API_RESULT), - API_ENTRY(CX2341X_ENC_MUTE_AUDIO, API_RESULT), - API_ENTRY(CX2341X_ENC_SET_VERT_CROP_LINE, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_MISC, API_FAST_RESULT), - /* Obsolete PULLDOWN API command */ - API_ENTRY(0xb1, API_CACHE), - - /* MPEG decoder API */ - API_ENTRY(CX2341X_DEC_PING_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_RESULT | API_NO_POLL), - API_ENTRY(CX2341X_DEC_STOP_PLAYBACK, API_RESULT), - API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED, API_RESULT), - API_ENTRY(CX2341X_DEC_STEP_VIDEO, API_RESULT), - API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE, API_CACHE), - API_ENTRY(CX2341X_DEC_GET_XFER_INFO, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_GET_DMA_STATUS, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST, API_DMA | API_HIGH_VOL), - API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK, API_RESULT), - API_ENTRY(CX2341X_DEC_HALT_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_SET_STANDARD, API_CACHE), - API_ENTRY(CX2341X_DEC_GET_VERSION, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_SET_STREAM_INPUT, API_CACHE), - API_ENTRY(CX2341X_DEC_GET_TIMING_INFO, API_RESULT /*| API_NO_WAIT_RES*/), - API_ENTRY(CX2341X_DEC_SET_AUDIO_MODE, API_CACHE), - API_ENTRY(CX2341X_DEC_SET_EVENT_NOTIFICATION, API_RESULT), - API_ENTRY(CX2341X_DEC_SET_DISPLAY_BUFFERS, API_CACHE), - API_ENTRY(CX2341X_DEC_EXTRACT_VBI, API_RESULT), - API_ENTRY(CX2341X_DEC_SET_DECODER_SOURCE, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_SET_PREBUFFERING, API_CACHE), - - /* OSD API */ - API_ENTRY(CX2341X_OSD_GET_FRAMEBUFFER, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_GET_PIXEL_FORMAT, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_PIXEL_FORMAT, API_CACHE), - API_ENTRY(CX2341X_OSD_GET_STATE, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_STATE, API_CACHE), - API_ENTRY(CX2341X_OSD_GET_OSD_COORDS, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_OSD_COORDS, API_CACHE), - API_ENTRY(CX2341X_OSD_GET_SCREEN_COORDS, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_SCREEN_COORDS, API_CACHE), - API_ENTRY(CX2341X_OSD_GET_GLOBAL_ALPHA, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_GLOBAL_ALPHA, API_CACHE), - API_ENTRY(CX2341X_OSD_SET_BLEND_COORDS, API_CACHE), - API_ENTRY(CX2341X_OSD_GET_FLICKER_STATE, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_FLICKER_STATE, API_CACHE), - API_ENTRY(CX2341X_OSD_BLT_COPY, API_RESULT), - API_ENTRY(CX2341X_OSD_BLT_FILL, API_RESULT), - API_ENTRY(CX2341X_OSD_BLT_TEXT, API_RESULT), - API_ENTRY(CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, API_CACHE), - API_ENTRY(CX2341X_OSD_SET_CHROMA_KEY, API_CACHE), - API_ENTRY(CX2341X_OSD_GET_ALPHA_CONTENT_INDEX, API_FAST_RESULT), - API_ENTRY(CX2341X_OSD_SET_ALPHA_CONTENT_INDEX, API_CACHE) -}; - -static int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb) -{ - u32 flags = readl(&mbdata->mbox[mb].flags); - int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE); - - /* if the mailbox is free, then try to claim it */ - if (is_free && !test_and_set_bit(mb, &mbdata->busy)) { - write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags); - return 1; - } - return 0; -} - -/* Try to find a free mailbox. Note mailbox 0 is reserved for DMA and so is not - attempted here. */ -static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int flags) -{ - unsigned long then = jiffies; - int i, mb; - int max_mbox = mbdata->max_mbox; - int retries = 100; - - /* All slow commands use the same mailbox, serializing them and also - leaving the other mailbox free for simple fast commands. */ - if ((flags & API_FAST_RESULT) == API_RESULT) - max_mbox = 1; - - /* find free non-DMA mailbox */ - for (i = 0; i < retries; i++) { - for (mb = 1; mb <= max_mbox; mb++) - if (try_mailbox(itv, mbdata, mb)) - return mb; - - /* Sleep before a retry, if not atomic */ - if (!(flags & API_NO_WAIT_MB)) { - if (time_after(jiffies, - then + msecs_to_jiffies(10*retries))) - break; - ivtv_msleep_timeout(10, 0); - } - } - return -ENODEV; -} - -static void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[]) -{ - int i; - - write_sync(cmd, &mbox->cmd); - write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout); - - for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) - write_sync(data[i], &mbox->data[i]); - - write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags); -} - -static void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata) -{ - int i; - - for (i = 0; i <= mbdata->max_mbox; i++) { - IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n", - i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags)); - write_sync(0, &mbdata->mbox[i].flags); - clear_bit(i, &mbdata->busy); - } -} - -static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) -{ - struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox; - volatile struct ivtv_mailbox __iomem *mbox; - int api_timeout = msecs_to_jiffies(1000); - int flags, mb, i; - unsigned long then; - - /* sanity checks */ - if (NULL == mbdata) { - IVTV_ERR("No mailbox allocated\n"); - return -ENODEV; - } - if (args < 0 || args > CX2341X_MBOX_MAX_DATA || - cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) { - IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args); - return -EINVAL; - } - - if (api_info[cmd].flags & API_HIGH_VOL) { - IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name); - } - else { - IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name); - } - - /* clear possibly uninitialized part of data array */ - for (i = args; i < CX2341X_MBOX_MAX_DATA; i++) - data[i] = 0; - - /* If this command was issued within the last 30 minutes and with identical - data, then just return 0 as there is no need to issue this command again. - Just an optimization to prevent unnecessary use of mailboxes. */ - if (itv->api_cache[cmd].last_jiffies && - time_before(jiffies, - itv->api_cache[cmd].last_jiffies + - msecs_to_jiffies(1800000)) && - !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) { - itv->api_cache[cmd].last_jiffies = jiffies; - return 0; - } - - flags = api_info[cmd].flags; - - if (flags & API_DMA) { - for (i = 0; i < 100; i++) { - mb = i % (mbdata->max_mbox + 1); - if (try_mailbox(itv, mbdata, mb)) { - write_mailbox(&mbdata->mbox[mb], cmd, args, data); - clear_bit(mb, &mbdata->busy); - return 0; - } - IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n", - api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags)); - } - IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name); - clear_all_mailboxes(itv, mbdata); - return -EBUSY; - } - - if ((flags & API_FAST_RESULT) == API_FAST_RESULT) - api_timeout = msecs_to_jiffies(100); - - mb = get_mailbox(itv, mbdata, flags); - if (mb < 0) { - IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name); - clear_all_mailboxes(itv, mbdata); - return -EBUSY; - } - mbox = &mbdata->mbox[mb]; - write_mailbox(mbox, cmd, args, data); - if (flags & API_CACHE) { - memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data)); - itv->api_cache[cmd].last_jiffies = jiffies; - } - if ((flags & API_RESULT) == 0) { - clear_bit(mb, &mbdata->busy); - return 0; - } - - /* Get results */ - then = jiffies; - - if (!(flags & API_NO_POLL)) { - /* First try to poll, then switch to delays */ - for (i = 0; i < 100; i++) { - if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE) - break; - } - } - while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { - if (time_after(jiffies, then + api_timeout)) { - IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name); - /* reset the mailbox, but it is likely too late already */ - write_sync(0, &mbox->flags); - clear_bit(mb, &mbdata->busy); - return -EIO; - } - if (flags & API_NO_WAIT_RES) - mdelay(1); - else - ivtv_msleep_timeout(1, 0); - } - if (time_after(jiffies, then + msecs_to_jiffies(100))) - IVTV_DEBUG_WARN("%s took %u jiffies\n", - api_info[cmd].name, - jiffies_to_msecs(jiffies - then)); - - for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++) - data[i] = readl(&mbox->data[i]); - write_sync(0, &mbox->flags); - clear_bit(mb, &mbdata->busy); - return 0; -} - -int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]) -{ - int res = ivtv_api_call(itv, cmd, args, data); - - /* Allow a single retry, probably already too late though. - If there is no free mailbox then that is usually an indication - of a more serious problem. */ - return (res == -EBUSY) ? ivtv_api_call(itv, cmd, args, data) : res; -} - -int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]) -{ - return ivtv_api(priv, cmd, in, data); -} - -int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...) -{ - va_list ap; - int i; - - va_start(ap, args); - for (i = 0; i < args; i++) { - data[i] = va_arg(ap, u32); - } - va_end(ap); - return ivtv_api(itv, cmd, args, data); -} - -int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - va_list ap; - int i; - - va_start(ap, args); - for (i = 0; i < args; i++) { - data[i] = va_arg(ap, u32); - } - va_end(ap); - return ivtv_api(itv, cmd, args, data); -} - -/* This one is for stuff that can't sleep.. irq handlers, etc.. */ -void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, - int argc, u32 data[]) -{ - volatile u32 __iomem *p = mbdata->mbox[mb].data; - int i; - for (i = 0; i < argc; i++, p++) - data[i] = readl(p); -} - -/* Wipe api cache */ -void ivtv_mailbox_cache_invalidate(struct ivtv *itv) -{ - int i; - for (i = 0; i < 256; i++) - itv->api_cache[i].last_jiffies = 0; -} diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h deleted file mode 100644 index 2c834d2cb56f..000000000000 --- a/drivers/media/video/ivtv/ivtv-mailbox.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - mailbox functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_MAILBOX_H -#define IVTV_MAILBOX_H - -#define IVTV_MBOX_DMA_END 8 -#define IVTV_MBOX_DMA 9 - -void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, - int argc, u32 data[]); -int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]); -int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...); -int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...); -int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]); -void ivtv_mailbox_cache_invalidate(struct ivtv *itv); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c deleted file mode 100644 index 7fde36e6d227..000000000000 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - buffer queues. - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-queue.h" - -int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes) -{ - if (s->buf_size - buf->bytesused < copybytes) - copybytes = s->buf_size - buf->bytesused; - if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) { - return -EFAULT; - } - buf->bytesused += copybytes; - return copybytes; -} - -void ivtv_buf_swap(struct ivtv_buffer *buf) -{ - int i; - - for (i = 0; i < buf->bytesused; i += 4) - swab32s((u32 *)(buf->buf + i)); -} - -void ivtv_queue_init(struct ivtv_queue *q) -{ - INIT_LIST_HEAD(&q->list); - q->buffers = 0; - q->length = 0; - q->bytesused = 0; -} - -void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q) -{ - unsigned long flags; - - /* clear the buffer if it is going to be enqueued to the free queue */ - if (q == &s->q_free) { - buf->bytesused = 0; - buf->readpos = 0; - buf->b_flags = 0; - buf->dma_xfer_cnt = 0; - } - spin_lock_irqsave(&s->qlock, flags); - list_add_tail(&buf->list, &q->list); - q->buffers++; - q->length += s->buf_size; - q->bytesused += buf->bytesused - buf->readpos; - spin_unlock_irqrestore(&s->qlock, flags); -} - -struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q) -{ - struct ivtv_buffer *buf = NULL; - unsigned long flags; - - spin_lock_irqsave(&s->qlock, flags); - if (!list_empty(&q->list)) { - buf = list_entry(q->list.next, struct ivtv_buffer, list); - list_del_init(q->list.next); - q->buffers--; - q->length -= s->buf_size; - q->bytesused -= buf->bytesused - buf->readpos; - } - spin_unlock_irqrestore(&s->qlock, flags); - return buf; -} - -static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from, - struct ivtv_queue *to, int clear) -{ - struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list); - - list_move_tail(from->list.next, &to->list); - from->buffers--; - from->length -= s->buf_size; - from->bytesused -= buf->bytesused - buf->readpos; - /* special handling for q_free */ - if (clear) - buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0; - to->buffers++; - to->length += s->buf_size; - to->bytesused += buf->bytesused - buf->readpos; -} - -/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'. - If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'. - If 'steal' != NULL, then buffers may also taken from that queue if - needed, but only if 'from' is the free queue. - - The buffer is automatically cleared if it goes to the free queue. It is - also cleared if buffers need to be taken from the 'steal' queue and - the 'from' queue is the free queue. - - When 'from' is q_free, then needed_bytes is compared to the total - available buffer length, otherwise needed_bytes is compared to the - bytesused value. For the 'steal' queue the total available buffer - length is always used. - - -ENOMEM is returned if the buffers could not be obtained, 0 if all - buffers where obtained from the 'from' list and if non-zero then - the number of stolen buffers is returned. */ -int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal, - struct ivtv_queue *to, int needed_bytes) -{ - unsigned long flags; - int rc = 0; - int from_free = from == &s->q_free; - int to_free = to == &s->q_free; - int bytes_available, bytes_steal; - - spin_lock_irqsave(&s->qlock, flags); - if (needed_bytes == 0) { - from_free = 1; - needed_bytes = from->length; - } - - bytes_available = from_free ? from->length : from->bytesused; - bytes_steal = (from_free && steal) ? steal->length : 0; - - if (bytes_available + bytes_steal < needed_bytes) { - spin_unlock_irqrestore(&s->qlock, flags); - return -ENOMEM; - } - while (bytes_available < needed_bytes) { - struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list); - u16 dma_xfer_cnt = buf->dma_xfer_cnt; - - /* move buffers from the tail of the 'steal' queue to the tail of the - 'from' queue. Always copy all the buffers with the same dma_xfer_cnt - value, this ensures that you do not end up with partial frame data - if one frame is stored in multiple buffers. */ - while (dma_xfer_cnt == buf->dma_xfer_cnt) { - list_move_tail(steal->list.prev, &from->list); - rc++; - steal->buffers--; - steal->length -= s->buf_size; - steal->bytesused -= buf->bytesused - buf->readpos; - buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0; - from->buffers++; - from->length += s->buf_size; - bytes_available += s->buf_size; - if (list_empty(&steal->list)) - break; - buf = list_entry(steal->list.prev, struct ivtv_buffer, list); - } - } - if (from_free) { - u32 old_length = to->length; - - while (to->length - old_length < needed_bytes) { - ivtv_queue_move_buf(s, from, to, 1); - } - } - else { - u32 old_bytesused = to->bytesused; - - while (to->bytesused - old_bytesused < needed_bytes) { - ivtv_queue_move_buf(s, from, to, to_free); - } - } - spin_unlock_irqrestore(&s->qlock, flags); - return rc; -} - -void ivtv_flush_queues(struct ivtv_stream *s) -{ - ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0); - ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0); - ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); - ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0); -} - -int ivtv_stream_alloc(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers; - int i; - - if (s->buffers == 0) - return 0; - - IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n", - s->dma != PCI_DMA_NONE ? "DMA " : "", - s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); - - s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); - if (s->sg_pending == NULL) { - IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name); - return -ENOMEM; - } - s->sg_pending_size = 0; - - s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); - if (s->sg_processing == NULL) { - IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name); - kfree(s->sg_pending); - s->sg_pending = NULL; - return -ENOMEM; - } - s->sg_processing_size = 0; - - s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), - GFP_KERNEL|__GFP_NOWARN); - if (s->sg_dma == NULL) { - IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name); - kfree(s->sg_pending); - s->sg_pending = NULL; - kfree(s->sg_processing); - s->sg_processing = NULL; - return -ENOMEM; - } - if (ivtv_might_use_dma(s)) { - s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, - sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); - ivtv_stream_sync_for_cpu(s); - } - - /* allocate stream buffers. Initially all buffers are in q_free. */ - for (i = 0; i < s->buffers; i++) { - struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), - GFP_KERNEL|__GFP_NOWARN); - - if (buf == NULL) - break; - buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN); - if (buf->buf == NULL) { - kfree(buf); - break; - } - INIT_LIST_HEAD(&buf->list); - if (ivtv_might_use_dma(s)) { - buf->dma_handle = pci_map_single(s->itv->pdev, - buf->buf, s->buf_size + 256, s->dma); - ivtv_buf_sync_for_cpu(s, buf); - } - ivtv_enqueue(s, buf, &s->q_free); - } - if (i == s->buffers) - return 0; - IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name); - ivtv_stream_free(s); - return -ENOMEM; -} - -void ivtv_stream_free(struct ivtv_stream *s) -{ - struct ivtv_buffer *buf; - - /* move all buffers to q_free */ - ivtv_flush_queues(s); - - /* empty q_free */ - while ((buf = ivtv_dequeue(s, &s->q_free))) { - if (ivtv_might_use_dma(s)) - pci_unmap_single(s->itv->pdev, buf->dma_handle, - s->buf_size + 256, s->dma); - kfree(buf->buf); - kfree(buf); - } - - /* Free SG Array/Lists */ - if (s->sg_dma != NULL) { - if (s->sg_handle != IVTV_DMA_UNMAPPED) { - pci_unmap_single(s->itv->pdev, s->sg_handle, - sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); - s->sg_handle = IVTV_DMA_UNMAPPED; - } - kfree(s->sg_pending); - kfree(s->sg_processing); - kfree(s->sg_dma); - s->sg_pending = NULL; - s->sg_processing = NULL; - s->sg_dma = NULL; - s->sg_pending_size = 0; - s->sg_processing_size = 0; - } -} diff --git a/drivers/media/video/ivtv/ivtv-queue.h b/drivers/media/video/ivtv/ivtv-queue.h deleted file mode 100644 index 91233839a26c..000000000000 --- a/drivers/media/video/ivtv/ivtv-queue.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - buffer queues. - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_QUEUE_H -#define IVTV_QUEUE_H - -#define IVTV_DMA_UNMAPPED ((u32) -1) -#define SLICED_VBI_PIO 0 - -/* ivtv_buffer utility functions */ - -static inline int ivtv_might_use_pio(struct ivtv_stream *s) -{ - return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI); -} - -static inline int ivtv_use_pio(struct ivtv_stream *s) -{ - struct ivtv *itv = s->itv; - - return s->dma == PCI_DMA_NONE || - (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); -} - -static inline int ivtv_might_use_dma(struct ivtv_stream *s) -{ - return s->dma != PCI_DMA_NONE; -} - -static inline int ivtv_use_dma(struct ivtv_stream *s) -{ - return !ivtv_use_pio(s); -} - -static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) -{ - if (ivtv_use_dma(s)) - pci_dma_sync_single_for_cpu(s->itv->pdev, buf->dma_handle, - s->buf_size + 256, s->dma); -} - -static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) -{ - if (ivtv_use_dma(s)) - pci_dma_sync_single_for_device(s->itv->pdev, buf->dma_handle, - s->buf_size + 256, s->dma); -} - -int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes); -void ivtv_buf_swap(struct ivtv_buffer *buf); - -/* ivtv_queue utility functions */ -void ivtv_queue_init(struct ivtv_queue *q); -void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q); -struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q); -int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal, - struct ivtv_queue *to, int needed_bytes); -void ivtv_flush_queues(struct ivtv_stream *s); - -/* ivtv_stream utility functions */ -int ivtv_stream_alloc(struct ivtv_stream *s); -void ivtv_stream_free(struct ivtv_stream *s); - -static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) -{ - if (ivtv_use_dma(s)) - pci_dma_sync_single_for_cpu(s->itv->pdev, s->sg_handle, - sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); -} - -static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) -{ - if (ivtv_use_dma(s)) - pci_dma_sync_single_for_device(s->itv->pdev, s->sg_handle, - sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); -} - -#endif diff --git a/drivers/media/video/ivtv/ivtv-routing.c b/drivers/media/video/ivtv/ivtv-routing.c deleted file mode 100644 index 8898c569a1c9..000000000000 --- a/drivers/media/video/ivtv/ivtv-routing.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - Audio/video-routing-related ivtv functions. - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-i2c.h" -#include "ivtv-cards.h" -#include "ivtv-gpio.h" -#include "ivtv-routing.h" - -#include <media/msp3400.h> -#include <media/m52790.h> -#include <media/upd64031a.h> -#include <media/upd64083.h> - -/* Selects the audio input and output according to the current - settings. */ -void ivtv_audio_set_io(struct ivtv *itv) -{ - const struct ivtv_card_audio_input *in; - u32 input, output = 0; - - /* Determine which input to use */ - if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) - in = &itv->card->radio_input; - else - in = &itv->card->audio_inputs[itv->audio_input]; - - /* handle muxer chips */ - input = in->muxer_input; - if (itv->card->hw_muxer & IVTV_HW_M52790) - output = M52790_OUT_STEREO; - v4l2_subdev_call(itv->sd_muxer, audio, s_routing, - input, output, 0); - - input = in->audio_input; - output = 0; - if (itv->card->hw_audio & IVTV_HW_MSP34XX) - output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); - ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, - input, output, 0); -} - -/* Selects the video input and output according to the current - settings. */ -void ivtv_video_set_io(struct ivtv *itv) -{ - int inp = itv->active_input; - u32 input; - u32 type; - - v4l2_subdev_call(itv->sd_video, video, s_routing, - itv->card->video_inputs[inp].video_input, 0, 0); - - type = itv->card->video_inputs[inp].video_type; - - if (type == IVTV_CARD_INPUT_VID_TUNER) { - input = 0; /* Tuner */ - } else if (type < IVTV_CARD_INPUT_COMPOSITE1) { - input = 2; /* S-Video */ - } else { - input = 1; /* Composite */ - } - - if (itv->card->hw_video & IVTV_HW_GPIO) - ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing, - input, 0, 0); - - if (itv->card->hw_video & IVTV_HW_UPD64031A) { - if (type == IVTV_CARD_INPUT_VID_TUNER || - type >= IVTV_CARD_INPUT_COMPOSITE1) { - /* Composite: GR on, connect to 3DYCS */ - input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE; - } else { - /* S-Video: GR bypassed, turn it off */ - input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE; - } - input |= itv->card->gr_config; - - ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing, - input, 0, 0); - } - - if (itv->card->hw_video & IVTV_HW_UPD6408X) { - input = UPD64083_YCS_MODE; - if (type > IVTV_CARD_INPUT_VID_TUNER && - type < IVTV_CARD_INPUT_COMPOSITE1) { - /* S-Video uses YCNR mode and internal Y-ADC, the - upd64031a is not used. */ - input |= UPD64083_YCNR_MODE; - } - else if (itv->card->hw_video & IVTV_HW_UPD64031A) { - /* Use upd64031a output for tuner and - composite(CX23416GYC only) inputs */ - if (type == IVTV_CARD_INPUT_VID_TUNER || - itv->card->type == IVTV_CARD_CX23416GYC) { - input |= UPD64083_EXT_Y_ADC; - } - } - ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing, - input, 0, 0); - } -} diff --git a/drivers/media/video/ivtv/ivtv-routing.h b/drivers/media/video/ivtv/ivtv-routing.h deleted file mode 100644 index c72a9731ca01..000000000000 --- a/drivers/media/video/ivtv/ivtv-routing.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Audio/video-routing-related ivtv functions. - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_ROUTING_H -#define IVTV_ROUTING_H - -void ivtv_audio_set_io(struct ivtv *itv); -void ivtv_video_set_io(struct ivtv *itv); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c deleted file mode 100644 index f08ec17cc3dc..000000000000 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - init/start/stop/exit stream functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* License: GPL - * Author: Kevin Thayer <nufan_wfk at yahoo dot com> - * - * This file will hold API related functions, both internal (firmware api) - * and external (v4l2, etc) - * - * ----- - * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> - * and Takeru KOMORIYA<komoriya@paken.org> - * - * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> - * using information provided by Jiun-Kuei Jung @ AVerMedia. - */ - -#include "ivtv-driver.h" -#include "ivtv-fileops.h" -#include "ivtv-queue.h" -#include "ivtv-mailbox.h" -#include "ivtv-ioctl.h" -#include "ivtv-irq.h" -#include "ivtv-yuv.h" -#include "ivtv-cards.h" -#include "ivtv-streams.h" -#include "ivtv-firmware.h" -#include <media/v4l2-event.h> - -static const struct v4l2_file_operations ivtv_v4l2_enc_fops = { - .owner = THIS_MODULE, - .read = ivtv_v4l2_read, - .write = ivtv_v4l2_write, - .open = ivtv_v4l2_open, - .unlocked_ioctl = video_ioctl2, - .release = ivtv_v4l2_close, - .poll = ivtv_v4l2_enc_poll, -}; - -static const struct v4l2_file_operations ivtv_v4l2_dec_fops = { - .owner = THIS_MODULE, - .read = ivtv_v4l2_read, - .write = ivtv_v4l2_write, - .open = ivtv_v4l2_open, - .unlocked_ioctl = video_ioctl2, - .release = ivtv_v4l2_close, - .poll = ivtv_v4l2_dec_poll, -}; - -#define IVTV_V4L2_DEC_MPG_OFFSET 16 /* offset from 0 to register decoder mpg v4l2 minors on */ -#define IVTV_V4L2_ENC_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ -#define IVTV_V4L2_ENC_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ -#define IVTV_V4L2_DEC_YUV_OFFSET 48 /* offset from 0 to register decoder yuv v4l2 minors on */ -#define IVTV_V4L2_DEC_VBI_OFFSET 8 /* offset from 0 to register decoder vbi input v4l2 minors on */ -#define IVTV_V4L2_DEC_VOUT_OFFSET 16 /* offset from 0 to register vbi output v4l2 minors on */ - -static struct { - const char *name; - int vfl_type; - int num_offset; - int dma, pio; - enum v4l2_buf_type buf_type; - u32 v4l2_caps; - const struct v4l2_file_operations *fops; -} ivtv_stream_info[] = { - { /* IVTV_ENC_STREAM_TYPE_MPG */ - "encoder MPG", - VFL_TYPE_GRABBER, 0, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_YUV */ - "encoder YUV", - VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, - V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_VBI */ - "encoder VBI", - VFL_TYPE_VBI, 0, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER | - V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_PCM */ - "encoder PCM", - VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET, - PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE, - V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_ENC_STREAM_TYPE_RAD */ - "encoder radio", - VFL_TYPE_RADIO, 0, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE, - V4L2_CAP_RADIO | V4L2_CAP_TUNER, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_DEC_STREAM_TYPE_MPG */ - "decoder MPG", - VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET, - PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, - V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_dec_fops - }, - { /* IVTV_DEC_STREAM_TYPE_VBI */ - "decoder VBI", - VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE, - V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE, - &ivtv_v4l2_enc_fops - }, - { /* IVTV_DEC_STREAM_TYPE_VOUT */ - "decoder VOUT", - VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET, - PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT, - V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_dec_fops - }, - { /* IVTV_DEC_STREAM_TYPE_YUV */ - "decoder YUV", - VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET, - PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT, - V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE, - &ivtv_v4l2_dec_fops - } -}; - -static void ivtv_stream_init(struct ivtv *itv, int type) -{ - struct ivtv_stream *s = &itv->streams[type]; - struct video_device *vdev = s->vdev; - - /* we need to keep vdev, so restore it afterwards */ - memset(s, 0, sizeof(*s)); - s->vdev = vdev; - - /* initialize ivtv_stream fields */ - s->itv = itv; - s->type = type; - s->name = ivtv_stream_info[type].name; - s->caps = ivtv_stream_info[type].v4l2_caps; - - if (ivtv_stream_info[type].pio) - s->dma = PCI_DMA_NONE; - else - s->dma = ivtv_stream_info[type].dma; - s->buf_size = itv->stream_buf_size[type]; - if (s->buf_size) - s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size; - spin_lock_init(&s->qlock); - init_waitqueue_head(&s->waitq); - s->sg_handle = IVTV_DMA_UNMAPPED; - ivtv_queue_init(&s->q_free); - ivtv_queue_init(&s->q_full); - ivtv_queue_init(&s->q_dma); - ivtv_queue_init(&s->q_predma); - ivtv_queue_init(&s->q_io); -} - -static int ivtv_prep_dev(struct ivtv *itv, int type) -{ - struct ivtv_stream *s = &itv->streams[type]; - int num_offset = ivtv_stream_info[type].num_offset; - int num = itv->instance + ivtv_first_minor + num_offset; - - /* These four fields are always initialized. If vdev == NULL, then - this stream is not in use. In that case no other fields but these - four can be used. */ - s->vdev = NULL; - s->itv = itv; - s->type = type; - s->name = ivtv_stream_info[type].name; - - /* Check whether the radio is supported */ - if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO)) - return 0; - if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return 0; - - /* User explicitly selected 0 buffers for these streams, so don't - create them. */ - if (ivtv_stream_info[type].dma != PCI_DMA_NONE && - itv->options.kilobytes[type] == 0) { - IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name); - return 0; - } - - ivtv_stream_init(itv, type); - - /* allocate and initialize the v4l2 video device structure */ - s->vdev = video_device_alloc(); - if (s->vdev == NULL) { - IVTV_ERR("Couldn't allocate v4l2 video_device for %s\n", s->name); - return -ENOMEM; - } - - snprintf(s->vdev->name, sizeof(s->vdev->name), "%s %s", - itv->v4l2_dev.name, s->name); - - s->vdev->num = num; - s->vdev->v4l2_dev = &itv->v4l2_dev; - s->vdev->fops = ivtv_stream_info[type].fops; - s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler; - s->vdev->release = video_device_release; - s->vdev->tvnorms = V4L2_STD_ALL; - s->vdev->lock = &itv->serialize_lock; - set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags); - ivtv_set_funcs(s->vdev); - return 0; -} - -/* Initialize v4l2 variables and prepare v4l2 devices */ -int ivtv_streams_setup(struct ivtv *itv) -{ - int type; - - /* Setup V4L2 Devices */ - for (type = 0; type < IVTV_MAX_STREAMS; type++) { - /* Prepare device */ - if (ivtv_prep_dev(itv, type)) - break; - - if (itv->streams[type].vdev == NULL) - continue; - - /* Allocate Stream */ - if (ivtv_stream_alloc(&itv->streams[type])) - break; - } - if (type == IVTV_MAX_STREAMS) - return 0; - - /* One or more streams could not be initialized. Clean 'em all up. */ - ivtv_streams_cleanup(itv, 0); - return -ENOMEM; -} - -static int ivtv_reg_dev(struct ivtv *itv, int type) -{ - struct ivtv_stream *s = &itv->streams[type]; - int vfl_type = ivtv_stream_info[type].vfl_type; - const char *name; - int num; - - if (s->vdev == NULL) - return 0; - - num = s->vdev->num; - /* card number + user defined offset + device offset */ - if (type != IVTV_ENC_STREAM_TYPE_MPG) { - struct ivtv_stream *s_mpg = &itv->streams[IVTV_ENC_STREAM_TYPE_MPG]; - - if (s_mpg->vdev) - num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset; - } - video_set_drvdata(s->vdev, s); - - /* Register device. First try the desired minor, then any free one. */ - if (video_register_device_no_warn(s->vdev, vfl_type, num)) { - IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n", - s->name, num); - video_device_release(s->vdev); - s->vdev = NULL; - return -ENOMEM; - } - name = video_device_node_name(s->vdev); - - switch (vfl_type) { - case VFL_TYPE_GRABBER: - IVTV_INFO("Registered device %s for %s (%d kB)\n", - name, s->name, itv->options.kilobytes[type]); - break; - case VFL_TYPE_RADIO: - IVTV_INFO("Registered device %s for %s\n", - name, s->name); - break; - case VFL_TYPE_VBI: - if (itv->options.kilobytes[type]) - IVTV_INFO("Registered device %s for %s (%d kB)\n", - name, s->name, itv->options.kilobytes[type]); - else - IVTV_INFO("Registered device %s for %s\n", - name, s->name); - break; - } - return 0; -} - -/* Register v4l2 devices */ -int ivtv_streams_register(struct ivtv *itv) -{ - int type; - int err = 0; - - /* Register V4L2 devices */ - for (type = 0; type < IVTV_MAX_STREAMS; type++) - err |= ivtv_reg_dev(itv, type); - - if (err == 0) - return 0; - - /* One or more streams could not be initialized. Clean 'em all up. */ - ivtv_streams_cleanup(itv, 1); - return -ENOMEM; -} - -/* Unregister v4l2 devices */ -void ivtv_streams_cleanup(struct ivtv *itv, int unregister) -{ - int type; - - /* Teardown all streams */ - for (type = 0; type < IVTV_MAX_STREAMS; type++) { - struct video_device *vdev = itv->streams[type].vdev; - - itv->streams[type].vdev = NULL; - if (vdev == NULL) - continue; - - ivtv_stream_free(&itv->streams[type]); - /* Unregister or release device */ - if (unregister) - video_unregister_device(vdev); - else - video_device_release(vdev); - } -} - -static void ivtv_vbi_setup(struct ivtv *itv) -{ - int raw = ivtv_raw_vbi(itv); - u32 data[CX2341X_MBOX_MAX_DATA]; - int lines; - int i; - - /* Reset VBI */ - ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); - - /* setup VBI registers */ - if (raw) - v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi); - else - v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced); - - /* determine number of lines and total number of VBI bytes. - A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 - The '- 1' byte is probably an unused U or V byte. Or something... - A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal - header, 42 data bytes + checksum (to be confirmed) */ - if (raw) { - lines = itv->vbi.count * 2; - } else { - lines = itv->is_60hz ? 24 : 38; - if (itv->is_60hz && (itv->hw_flags & IVTV_HW_CX25840)) - lines += 2; - } - - itv->vbi.enc_size = lines * (raw ? itv->vbi.raw_size : itv->vbi.sliced_size); - - /* Note: sliced vs raw flag doesn't seem to have any effect - TODO: check mode (0x02) value with older ivtv versions. */ - data[0] = raw | 0x02 | (0xbd << 8); - - /* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */ - data[1] = 1; - /* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */ - data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size); - /* The start/stop codes determine which VBI lines end up in the raw VBI data area. - The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line - is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video) - code. These values for raw VBI are obtained from a driver disassembly. The sliced - start/stop codes was deduced from this, but they do not appear in the driver. - Other code pairs that I found are: 0x250E6249/0x13545454 and 0x25256262/0x38137F54. - However, I have no idea what these values are for. */ - if (itv->hw_flags & IVTV_HW_CX25840) { - /* Setup VBI for the cx25840 digitizer */ - if (raw) { - data[3] = 0x20602060; - data[4] = 0x30703070; - } else { - data[3] = 0xB0F0B0F0; - data[4] = 0xA0E0A0E0; - } - /* Lines per frame */ - data[5] = lines; - /* bytes per line */ - data[6] = (raw ? itv->vbi.raw_size : itv->vbi.sliced_size); - } else { - /* Setup VBI for the saa7115 digitizer */ - if (raw) { - data[3] = 0x25256262; - data[4] = 0x387F7F7F; - } else { - data[3] = 0xABABECEC; - data[4] = 0xB6F1F1F1; - } - /* Lines per frame */ - data[5] = lines; - /* bytes per line */ - data[6] = itv->vbi.enc_size / lines; - } - - IVTV_DEBUG_INFO( - "Setup VBI API header 0x%08x pkts %d buffs %d ln %d sz %d\n", - data[0], data[1], data[2], data[5], data[6]); - - ivtv_api(itv, CX2341X_ENC_SET_VBI_CONFIG, 7, data); - - /* returns the VBI encoder memory area. */ - itv->vbi.enc_start = data[2]; - itv->vbi.fpi = data[0]; - if (!itv->vbi.fpi) - itv->vbi.fpi = 1; - - IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n", - itv->vbi.enc_start, data[1], itv->vbi.fpi); - - /* select VBI lines. - Note that the sliced argument seems to have no effect. */ - for (i = 2; i <= 24; i++) { - int valid; - - if (itv->is_60hz) { - valid = i >= 10 && i < 22; - } else { - valid = i >= 6 && i < 24; - } - ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, i - 1, - valid, 0 , 0, 0); - ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, (i - 1) | 0x80000000, - valid, 0, 0, 0); - } - - /* Remaining VBI questions: - - Is it possible to select particular VBI lines only for inclusion in the MPEG - stream? Currently you can only get the first X lines. - - Is mixed raw and sliced VBI possible? - - What's the meaning of the raw/sliced flag? - - What's the meaning of params 2, 3 & 4 of the Select VBI command? */ -} - -int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv *itv = s->itv; - int captype = 0, subtype = 0; - int enable_passthrough = 0; - - if (s->vdev == NULL) - return -EINVAL; - - IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name); - - switch (s->type) { - case IVTV_ENC_STREAM_TYPE_MPG: - captype = 0; - subtype = 3; - - /* Stop Passthrough */ - if (itv->output_mode == OUT_PASSTHROUGH) { - ivtv_passthrough_mode(itv, 0); - enable_passthrough = 1; - } - itv->mpg_data_received = itv->vbi_data_inserted = 0; - itv->dualwatch_jiffies = jiffies; - itv->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode); - itv->search_pack_header = 0; - break; - - case IVTV_ENC_STREAM_TYPE_YUV: - if (itv->output_mode == OUT_PASSTHROUGH) { - captype = 2; - subtype = 11; /* video+audio+decoder */ - break; - } - captype = 1; - subtype = 1; - break; - case IVTV_ENC_STREAM_TYPE_PCM: - captype = 1; - subtype = 2; - break; - case IVTV_ENC_STREAM_TYPE_VBI: - captype = 1; - subtype = 4; - - itv->vbi.frame = 0; - itv->vbi.inserted_frame = 0; - memset(itv->vbi.sliced_mpeg_size, - 0, sizeof(itv->vbi.sliced_mpeg_size)); - break; - default: - return -EINVAL; - } - s->subtype = subtype; - s->buffers_stolen = 0; - - /* Clear Streamoff flags in case left from last capture */ - clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - - if (atomic_read(&itv->capturing) == 0) { - int digitizer; - - /* Always use frame based mode. Experiments have demonstrated that byte - stream based mode results in dropped frames and corruption. Not often, - but occasionally. Many thanks go to Leonard Orb who spent a lot of - effort and time trying to trace the cause of the drop outs. */ - /* 1 frame per DMA */ - /*ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 128, 0); */ - ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 1, 1); - - /* Stuff from Windows, we don't know what it is */ - ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, 0); - /* According to the docs, this should be correct. However, this is - untested. I don't dare enable this without having tested it. - Only very few old cards actually have this hardware combination. - ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, - ((itv->hw_flags & IVTV_HW_SAA7114) && itv->is_60hz) ? 10001 : 0); - */ - ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 3, !itv->has_cx23415); - ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 8, 0); - ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 4, 1); - ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12); - - /* assign placeholder */ - ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X)) - digitizer = 0xF1; - else if (itv->card->hw_all & IVTV_HW_SAA7114) - digitizer = 0xEF; - else /* cx25840 */ - digitizer = 0x140; - - ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer); - - /* Setup VBI */ - if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) { - ivtv_vbi_setup(itv); - } - - /* assign program index info. Mask 7: select I/P/B, Num_req: 400 max */ - ivtv_vapi_result(itv, data, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, 7, 400); - itv->pgm_info_offset = data[0]; - itv->pgm_info_num = data[1]; - itv->pgm_info_write_idx = 0; - itv->pgm_info_read_idx = 0; - - IVTV_DEBUG_INFO("PGM Index at 0x%08x with %d elements\n", - itv->pgm_info_offset, itv->pgm_info_num); - - /* Setup API for Stream */ - cx2341x_handler_setup(&itv->cxhdl); - - /* mute if capturing radio */ - if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) - ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1, - 1 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8)); - } - - /* Vsync Setup */ - if (itv->has_cx23415 && !test_and_set_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { - /* event notification (on) */ - ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_ENC_VIM_RST, -1); - ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); - } - - if (atomic_read(&itv->capturing) == 0) { - /* Clear all Pending Interrupts */ - ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); - - clear_bit(IVTV_F_I_EOS, &itv->i_flags); - - cx2341x_handler_set_busy(&itv->cxhdl, 1); - - /* Initialize Digitizer for Capture */ - /* Avoid tinny audio problem - ensure audio clocks are going */ - v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1); - /* Avoid unpredictable PCI bus hang - disable video clocks */ - v4l2_subdev_call(itv->sd_video, video, s_stream, 0); - ivtv_msleep_timeout(300, 0); - ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); - v4l2_subdev_call(itv->sd_video, video, s_stream, 1); - } - - /* begin_capture */ - if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype)) - { - IVTV_DEBUG_WARN( "Error starting capture!\n"); - return -EINVAL; - } - - /* Start Passthrough */ - if (enable_passthrough) { - ivtv_passthrough_mode(itv, 1); - } - - if (s->type == IVTV_ENC_STREAM_TYPE_VBI) - ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); - else - ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); - - /* you're live! sit back and await interrupts :) */ - atomic_inc(&itv->capturing); - return 0; -} - -static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - struct ivtv *itv = s->itv; - int datatype; - u16 width; - u16 height; - - if (s->vdev == NULL) - return -EINVAL; - - IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); - - width = itv->cxhdl.width; - height = itv->cxhdl.height; - - /* set audio mode to left/stereo for dual/stereo mode. */ - ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); - - /* set number of internal decoder buffers */ - ivtv_vapi(itv, CX2341X_DEC_SET_DISPLAY_BUFFERS, 1, 0); - - /* prebuffering */ - ivtv_vapi(itv, CX2341X_DEC_SET_PREBUFFERING, 1, 1); - - /* extract from user packets */ - ivtv_vapi_result(itv, data, CX2341X_DEC_EXTRACT_VBI, 1, 1); - itv->vbi.dec_start = data[0]; - - IVTV_DEBUG_INFO("Decoder VBI RE-Insert start 0x%08x size 0x%08x\n", - itv->vbi.dec_start, data[1]); - - /* set decoder source settings */ - /* Data type: 0 = mpeg from host, - 1 = yuv from encoder, - 2 = yuv_from_host */ - switch (s->type) { - case IVTV_DEC_STREAM_TYPE_YUV: - if (itv->output_mode == OUT_PASSTHROUGH) { - datatype = 1; - } else { - /* Fake size to avoid switching video standard */ - datatype = 2; - width = 720; - height = itv->is_out_50hz ? 576 : 480; - } - IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype); - break; - case IVTV_DEC_STREAM_TYPE_MPG: - default: - datatype = 0; - break; - } - if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, - width, height, itv->cxhdl.audio_properties)) { - IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); - } - - /* Decoder sometimes dies here, so wait a moment */ - ivtv_msleep_timeout(10, 0); - - /* Known failure point for firmware, so check */ - return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream"); -} - -int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset) -{ - struct ivtv *itv = s->itv; - int rc; - - if (s->vdev == NULL) - return -EINVAL; - - if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) - return 0; /* already started */ - - IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset); - - rc = ivtv_setup_v4l2_decode_stream(s); - if (rc < 0) { - clear_bit(IVTV_F_S_STREAMING, &s->s_flags); - return rc; - } - - /* set dma size to 65536 bytes */ - ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536); - - /* Clear Streamoff */ - clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - - /* Zero out decoder counters */ - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[0]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[1]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[2]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[3]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]); - writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[3]); - - /* turn on notification of dual/stereo mode change */ - ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); - - /* start playback */ - ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0); - - /* Let things settle before we actually start */ - ivtv_msleep_timeout(10, 0); - - /* Clear the following Interrupt mask bits for decoding */ - ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE); - IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask); - - /* you're live! sit back and await interrupts :) */ - atomic_inc(&itv->decoding); - return 0; -} - -void ivtv_stop_all_captures(struct ivtv *itv) -{ - int i; - - for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) { - struct ivtv_stream *s = &itv->streams[i]; - - if (s->vdev == NULL) - continue; - if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) { - ivtv_stop_v4l2_encode_stream(s, 0); - } - } -} - -int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end) -{ - struct ivtv *itv = s->itv; - DECLARE_WAITQUEUE(wait, current); - int cap_type; - int stopmode; - - if (s->vdev == NULL) - return -EINVAL; - - /* This function assumes that you are allowed to stop the capture - and that we are actually capturing */ - - IVTV_DEBUG_INFO("Stop Capture\n"); - - if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) - return 0; - if (atomic_read(&itv->capturing) == 0) - return 0; - - switch (s->type) { - case IVTV_ENC_STREAM_TYPE_YUV: - cap_type = 1; - break; - case IVTV_ENC_STREAM_TYPE_PCM: - cap_type = 1; - break; - case IVTV_ENC_STREAM_TYPE_VBI: - cap_type = 1; - break; - case IVTV_ENC_STREAM_TYPE_MPG: - default: - cap_type = 0; - break; - } - - /* Stop Capture Mode */ - if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { - stopmode = 0; - } else { - stopmode = 1; - } - - /* end_capture */ - /* when: 0 = end of GOP 1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */ - ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype); - - if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { - if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) { - /* only run these if we're shutting down the last cap */ - unsigned long duration; - unsigned long then = jiffies; - - add_wait_queue(&itv->eos_waitq, &wait); - - set_current_state(TASK_INTERRUPTIBLE); - - /* wait 2s for EOS interrupt */ - while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) && - time_before(jiffies, - then + msecs_to_jiffies(2000))) { - schedule_timeout(msecs_to_jiffies(10)); - } - - /* To convert jiffies to ms, we must multiply by 1000 - * and divide by HZ. To avoid runtime division, we - * convert this to multiplication by 1000/HZ. - * Since integer division truncates, we get the best - * accuracy if we do a rounding calculation of the constant. - * Think of the case where HZ is 1024. - */ - duration = ((1000 + HZ / 2) / HZ) * (jiffies - then); - - if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) { - IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name); - IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration); - } else { - IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&itv->eos_waitq, &wait); - set_bit(IVTV_F_S_STREAMOFF, &s->s_flags); - } - - /* Handle any pending interrupts */ - ivtv_msleep_timeout(100, 0); - } - - atomic_dec(&itv->capturing); - - /* Clear capture and no-read bits */ - clear_bit(IVTV_F_S_STREAMING, &s->s_flags); - - if (s->type == IVTV_ENC_STREAM_TYPE_VBI) - ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP); - - if (atomic_read(&itv->capturing) > 0) { - return 0; - } - - cx2341x_handler_set_busy(&itv->cxhdl, 0); - - /* Set the following Interrupt mask bits for capture */ - ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE); - del_timer(&itv->dma_timer); - - /* event notification (off) */ - if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) { - /* type: 0 = refresh */ - /* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */ - ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1); - ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST); - } - - /* Raw-passthrough is implied on start. Make sure it's stopped so - the encoder will re-initialize when next started */ - ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7); - - wake_up(&s->waitq); - - return 0; -} - -int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) -{ - static const struct v4l2_event ev = { - .type = V4L2_EVENT_EOS, - }; - struct ivtv *itv = s->itv; - - if (s->vdev == NULL) - return -EINVAL; - - if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG) - return -EINVAL; - - if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags)) - return 0; - - IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags); - - /* Stop Decoder */ - if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) { - u32 tmp = 0; - - /* Wait until the decoder is no longer running */ - if (pts) { - ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, - 0, (u32)(pts & 0xffffffff), (u32)(pts >> 32)); - } - while (1) { - u32 data[CX2341X_MBOX_MAX_DATA]; - ivtv_vapi_result(itv, data, CX2341X_DEC_GET_XFER_INFO, 0); - if (s->q_full.buffers + s->q_dma.buffers == 0) { - if (tmp == data[3]) - break; - tmp = data[3]; - } - if (ivtv_msleep_timeout(100, 1)) - break; - } - } - ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0); - - /* turn off notification of dual/stereo mode change */ - ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1); - - ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE); - del_timer(&itv->dma_timer); - - clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags); - clear_bit(IVTV_F_S_STREAMING, &s->s_flags); - ivtv_flush_queues(s); - - /* decoder needs time to settle */ - ivtv_msleep_timeout(40, 0); - - /* decrement decoding */ - atomic_dec(&itv->decoding); - - set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags); - wake_up(&itv->event_waitq); - v4l2_event_queue(s->vdev, &ev); - - /* wake up wait queues */ - wake_up(&s->waitq); - - return 0; -} - -int ivtv_passthrough_mode(struct ivtv *itv, int enable) -{ - struct ivtv_stream *yuv_stream = &itv->streams[IVTV_ENC_STREAM_TYPE_YUV]; - struct ivtv_stream *dec_stream = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV]; - - if (yuv_stream->vdev == NULL || dec_stream->vdev == NULL) - return -EINVAL; - - IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n"); - - /* Prevent others from starting/stopping streams while we - initiate/terminate passthrough mode */ - if (enable) { - if (itv->output_mode == OUT_PASSTHROUGH) { - return 0; - } - if (ivtv_set_output_mode(itv, OUT_PASSTHROUGH) != OUT_PASSTHROUGH) - return -EBUSY; - - /* Fully initialize stream, and then unflag init */ - set_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags); - set_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags); - - /* Setup YUV Decoder */ - ivtv_setup_v4l2_decode_stream(dec_stream); - - /* Start Decoder */ - ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1); - atomic_inc(&itv->decoding); - - /* Setup capture if not already done */ - if (atomic_read(&itv->capturing) == 0) { - cx2341x_handler_setup(&itv->cxhdl); - cx2341x_handler_set_busy(&itv->cxhdl, 1); - } - - /* Start Passthrough Mode */ - ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, 2, 11); - atomic_inc(&itv->capturing); - return 0; - } - - if (itv->output_mode != OUT_PASSTHROUGH) - return 0; - - /* Stop Passthrough Mode */ - ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 11); - ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, 1, 0, 0); - - atomic_dec(&itv->capturing); - atomic_dec(&itv->decoding); - clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags); - clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags); - itv->output_mode = OUT_NONE; - if (atomic_read(&itv->capturing) == 0) - cx2341x_handler_set_busy(&itv->cxhdl, 0); - - return 0; -} diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h deleted file mode 100644 index a653a5136417..000000000000 --- a/drivers/media/video/ivtv/ivtv-streams.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - init/start/stop/exit stream functions - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_STREAMS_H -#define IVTV_STREAMS_H - -int ivtv_streams_setup(struct ivtv *itv); -int ivtv_streams_register(struct ivtv *itv); -void ivtv_streams_cleanup(struct ivtv *itv, int unregister); - -/* Capture related */ -int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s); -int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end); -int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset); -int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts); - -void ivtv_stop_all_captures(struct ivtv *itv); -int ivtv_passthrough_mode(struct ivtv *itv, int enable); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c deleted file mode 100644 index 7338cb2d0a38..000000000000 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - User DMA - - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-udma.h" - -void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size) -{ - dma_page->uaddr = first & PAGE_MASK; - dma_page->offset = first & ~PAGE_MASK; - dma_page->tail = 1 + ((first+size-1) & ~PAGE_MASK); - dma_page->first = (first & PAGE_MASK) >> PAGE_SHIFT; - dma_page->last = ((first+size-1) & PAGE_MASK) >> PAGE_SHIFT; - dma_page->page_count = dma_page->last - dma_page->first + 1; - if (dma_page->page_count == 1) dma_page->tail -= dma_page->offset; -} - -int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset) -{ - int i, offset; - unsigned long flags; - - if (map_offset < 0) - return map_offset; - - offset = dma_page->offset; - - /* Fill SG Array with new values */ - for (i = 0; i < dma_page->page_count; i++) { - unsigned int len = (i == dma_page->page_count - 1) ? - dma_page->tail : PAGE_SIZE - offset; - - if (PageHighMem(dma->map[map_offset])) { - void *src; - - if (dma->bouncemap[map_offset] == NULL) - dma->bouncemap[map_offset] = alloc_page(GFP_KERNEL); - if (dma->bouncemap[map_offset] == NULL) - return -1; - local_irq_save(flags); - src = kmap_atomic(dma->map[map_offset]) + offset; - memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); - kunmap_atomic(src); - local_irq_restore(flags); - sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset); - } - else { - sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset); - } - offset = 0; - map_offset++; - } - return map_offset; -} - -void ivtv_udma_fill_sg_array (struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split) { - int i; - struct scatterlist *sg; - - for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) { - dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg)); - dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg)); - dma->SGarray[i].dst = cpu_to_le32(buffer_offset); - buffer_offset += sg_dma_len(sg); - - split -= sg_dma_len(sg); - if (split == 0) - buffer_offset = buffer_offset_2; - } -} - -/* User DMA Buffers */ -void ivtv_udma_alloc(struct ivtv *itv) -{ - if (itv->udma.SG_handle == 0) { - /* Map DMA Page Array Buffer */ - itv->udma.SG_handle = pci_map_single(itv->pdev, itv->udma.SGarray, - sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); - ivtv_udma_sync_for_cpu(itv); - } -} - -int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, - void __user *userbuf, int size_in_bytes) -{ - struct ivtv_dma_page_info user_dma; - struct ivtv_user_dma *dma = &itv->udma; - int i, err; - - IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr); - - /* Still in USE */ - if (dma->SG_length || dma->page_count) { - IVTV_DEBUG_WARN("ivtv_udma_setup: SG_length %d page_count %d still full?\n", - dma->SG_length, dma->page_count); - return -EBUSY; - } - - ivtv_udma_get_page_info(&user_dma, (unsigned long)userbuf, size_in_bytes); - - if (user_dma.page_count <= 0) { - IVTV_DEBUG_WARN("ivtv_udma_setup: Error %d page_count from %d bytes %d offset\n", - user_dma.page_count, size_in_bytes, user_dma.offset); - return -EINVAL; - } - - /* Get user pages for DMA Xfer */ - down_read(¤t->mm->mmap_sem); - err = get_user_pages(current, current->mm, - user_dma.uaddr, user_dma.page_count, 0, 1, dma->map, NULL); - up_read(¤t->mm->mmap_sem); - - if (user_dma.page_count != err) { - IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n", - err, user_dma.page_count); - if (err >= 0) { - for (i = 0; i < err; i++) - put_page(dma->map[i]); - return -EINVAL; - } - return err; - } - - dma->page_count = user_dma.page_count; - - /* Fill SG List with new values */ - if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) { - for (i = 0; i < dma->page_count; i++) { - put_page(dma->map[i]); - } - dma->page_count = 0; - return -ENOMEM; - } - - /* Map SG List */ - dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); - - /* Fill SG Array with new values */ - ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1); - - /* Tag SG Array with Interrupt Bit */ - dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000); - - ivtv_udma_sync_for_device(itv); - return dma->page_count; -} - -void ivtv_udma_unmap(struct ivtv *itv) -{ - struct ivtv_user_dma *dma = &itv->udma; - int i; - - IVTV_DEBUG_INFO("ivtv_unmap_user_dma\n"); - - /* Nothing to free */ - if (dma->page_count == 0) - return; - - /* Unmap Scatterlist */ - if (dma->SG_length) { - pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); - dma->SG_length = 0; - } - /* sync DMA */ - ivtv_udma_sync_for_cpu(itv); - - /* Release User Pages */ - for (i = 0; i < dma->page_count; i++) { - put_page(dma->map[i]); - } - dma->page_count = 0; -} - -void ivtv_udma_free(struct ivtv *itv) -{ - int i; - - /* Unmap SG Array */ - if (itv->udma.SG_handle) { - pci_unmap_single(itv->pdev, itv->udma.SG_handle, - sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); - } - - /* Unmap Scatterlist */ - if (itv->udma.SG_length) { - pci_unmap_sg(itv->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE); - } - - for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) { - if (itv->udma.bouncemap[i]) - __free_page(itv->udma.bouncemap[i]); - } -} - -void ivtv_udma_start(struct ivtv *itv) -{ - IVTV_DEBUG_DMA("start UDMA\n"); - write_reg(itv->udma.SG_handle, IVTV_REG_DECDMAADDR); - write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER); - set_bit(IVTV_F_I_DMA, &itv->i_flags); - set_bit(IVTV_F_I_UDMA, &itv->i_flags); - clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags); -} - -void ivtv_udma_prepare(struct ivtv *itv) -{ - unsigned long flags; - - spin_lock_irqsave(&itv->dma_reg_lock, flags); - if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) - ivtv_udma_start(itv); - else - set_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags); - spin_unlock_irqrestore(&itv->dma_reg_lock, flags); -} diff --git a/drivers/media/video/ivtv/ivtv-udma.h b/drivers/media/video/ivtv/ivtv-udma.h deleted file mode 100644 index ee3c9efb5b72..000000000000 --- a/drivers/media/video/ivtv/ivtv-udma.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - Copyright (C) 2006-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_UDMA_H -#define IVTV_UDMA_H - -/* User DMA functions */ -void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size); -int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset); -void ivtv_udma_fill_sg_array(struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split); -int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr, - void __user *userbuf, int size_in_bytes); -void ivtv_udma_unmap(struct ivtv *itv); -void ivtv_udma_free(struct ivtv *itv); -void ivtv_udma_alloc(struct ivtv *itv); -void ivtv_udma_prepare(struct ivtv *itv); -void ivtv_udma_start(struct ivtv *itv); - -static inline void ivtv_udma_sync_for_device(struct ivtv *itv) -{ - pci_dma_sync_single_for_device(itv->pdev, itv->udma.SG_handle, - sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); -} - -static inline void ivtv_udma_sync_for_cpu(struct ivtv *itv) -{ - pci_dma_sync_single_for_cpu(itv->pdev, itv->udma.SG_handle, - sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE); -} - -#endif diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c deleted file mode 100644 index 293db806d936..000000000000 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - Vertical Blank Interval support functions - Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-i2c.h" -#include "ivtv-ioctl.h" -#include "ivtv-queue.h" -#include "ivtv-cards.h" -#include "ivtv-vbi.h" - -static void ivtv_set_vps(struct ivtv *itv, int enabled) -{ - struct v4l2_sliced_vbi_data data; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return; - data.id = V4L2_SLICED_VPS; - data.field = 0; - data.line = enabled ? 16 : 0; - data.data[2] = itv->vbi.vps_payload.data[0]; - data.data[8] = itv->vbi.vps_payload.data[1]; - data.data[9] = itv->vbi.vps_payload.data[2]; - data.data[10] = itv->vbi.vps_payload.data[3]; - data.data[11] = itv->vbi.vps_payload.data[4]; - ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); -} - -static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) -{ - struct v4l2_sliced_vbi_data data; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return; - data.id = V4L2_SLICED_CAPTION_525; - data.field = 0; - data.line = (mode & 1) ? 21 : 0; - data.data[0] = cc->odd[0]; - data.data[1] = cc->odd[1]; - ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); - data.field = 1; - data.line = (mode & 2) ? 21 : 0; - data.data[0] = cc->even[0]; - data.data[1] = cc->even[1]; - ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); -} - -static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) -{ - struct v4l2_sliced_vbi_data data; - - if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) - return; - /* When using a 50 Hz system, always turn on the - wide screen signal with 4x3 ratio as the default. - Turning this signal on and off can confuse certain - TVs. As far as I can tell there is no reason not to - transmit this signal. */ - if ((itv->std_out & V4L2_STD_625_50) && !enabled) { - enabled = 1; - mode = 0x08; /* 4x3 full format */ - } - data.id = V4L2_SLICED_WSS_625; - data.field = 0; - data.line = enabled ? 23 : 0; - data.data[0] = mode & 0xff; - data.data[1] = (mode >> 8) & 0xff; - ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data); -} - -static int odd_parity(u8 c) -{ - c ^= (c >> 4); - c ^= (c >> 2); - c ^= (c >> 1); - - return c & 1; -} - -static void ivtv_write_vbi_line(struct ivtv *itv, - const struct v4l2_sliced_vbi_data *d, - struct vbi_cc *cc, int *found_cc) -{ - struct vbi_info *vi = &itv->vbi; - - if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { - if (d->field) { - cc->even[0] = d->data[0]; - cc->even[1] = d->data[1]; - } else { - cc->odd[0] = d->data[0]; - cc->odd[1] = d->data[1]; - } - *found_cc = 1; - } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { - struct vbi_vps vps; - - vps.data[0] = d->data[2]; - vps.data[1] = d->data[8]; - vps.data[2] = d->data[9]; - vps.data[3] = d->data[10]; - vps.data[4] = d->data[11]; - if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { - vi->vps_payload = vps; - set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); - } - } else if (d->id == V4L2_SLICED_WSS_625 && - d->line == 23 && d->field == 0) { - int wss = d->data[0] | d->data[1] << 8; - - if (vi->wss_payload != wss) { - vi->wss_payload = wss; - set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); - } - } -} - -static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc) -{ - struct vbi_info *vi = &itv->vbi; - - if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { - memcpy(&vi->cc_payload[vi->cc_payload_idx], cc, - sizeof(struct vbi_cc)); - vi->cc_payload_idx++; - set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); - } -} - -static void ivtv_write_vbi(struct ivtv *itv, - const struct v4l2_sliced_vbi_data *sliced, - size_t cnt) -{ - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - int found_cc = 0; - size_t i; - - for (i = 0; i < cnt; i++) - ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); - - if (found_cc) - ivtv_write_vbi_cc_lines(itv, &cc); -} - -ssize_t -ivtv_write_vbi_from_user(struct ivtv *itv, - const struct v4l2_sliced_vbi_data __user *sliced, - size_t cnt) -{ - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - int found_cc = 0; - size_t i; - struct v4l2_sliced_vbi_data d; - ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data); - - for (i = 0; i < cnt; i++) { - if (copy_from_user(&d, sliced + i, - sizeof(struct v4l2_sliced_vbi_data))) { - ret = -EFAULT; - break; - } - ivtv_write_vbi_line(itv, &d, &cc, &found_cc); - } - - if (found_cc) - ivtv_write_vbi_cc_lines(itv, &cc); - - return ret; -} - -static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) -{ - int line = 0; - int i; - u32 linemask[2] = { 0, 0 }; - unsigned short size; - static const u8 mpeg_hdr_data[] = { - 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66, - 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff, - 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80, - 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff - }; - const int sd = sizeof(mpeg_hdr_data); /* start of vbi data */ - int idx = itv->vbi.frame % IVTV_VBI_FRAMES; - u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0]; - - for (i = 0; i < lines; i++) { - int f, l; - - if (itv->vbi.sliced_data[i].id == 0) - continue; - - l = itv->vbi.sliced_data[i].line - 6; - f = itv->vbi.sliced_data[i].field; - if (f) - l += 18; - if (l < 32) - linemask[0] |= (1 << l); - else - linemask[1] |= (1 << (l - 32)); - dst[sd + 12 + line * 43] = - ivtv_service2vbi(itv->vbi.sliced_data[i].id); - memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42); - line++; - } - memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data)); - if (line == 36) { - /* All lines are used, so there is no space for the linemask - (the max size of the VBI data is 36 * 43 + 4 bytes). - So in this case we use the magic number 'ITV0'. */ - memcpy(dst + sd, "ITV0", 4); - memcpy(dst + sd + 4, dst + sd + 12, line * 43); - size = 4 + ((43 * line + 3) & ~3); - } else { - memcpy(dst + sd, "itv0", 4); - cpu_to_le32s(&linemask[0]); - cpu_to_le32s(&linemask[1]); - memcpy(dst + sd + 4, &linemask[0], 8); - size = 12 + ((43 * line + 3) & ~3); - } - dst[4+16] = (size + 10) >> 8; - dst[5+16] = (size + 10) & 0xff; - dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6); - dst[10+16] = (pts_stamp >> 22) & 0xff; - dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff); - dst[12+16] = (pts_stamp >> 7) & 0xff; - dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1); - itv->vbi.sliced_mpeg_size[idx] = sd + size; -} - -static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p) -{ - u32 linemask[2]; - int i, l, id2; - int line = 0; - - if (!memcmp(p, "itv0", 4)) { - memcpy(linemask, p + 4, 8); - p += 12; - } else if (!memcmp(p, "ITV0", 4)) { - linemask[0] = 0xffffffff; - linemask[1] = 0xf; - p += 4; - } else { - /* unknown VBI data, convert to empty VBI frame */ - linemask[0] = linemask[1] = 0; - } - for (i = 0; i < 36; i++) { - int err = 0; - - if (i < 32 && !(linemask[0] & (1 << i))) - continue; - if (i >= 32 && !(linemask[1] & (1 << (i - 32)))) - continue; - id2 = *p & 0xf; - switch (id2) { - case IVTV_SLICED_TYPE_TELETEXT_B: - id2 = V4L2_SLICED_TELETEXT_B; - break; - case IVTV_SLICED_TYPE_CAPTION_525: - id2 = V4L2_SLICED_CAPTION_525; - err = !odd_parity(p[1]) || !odd_parity(p[2]); - break; - case IVTV_SLICED_TYPE_VPS: - id2 = V4L2_SLICED_VPS; - break; - case IVTV_SLICED_TYPE_WSS_625: - id2 = V4L2_SLICED_WSS_625; - break; - default: - id2 = 0; - break; - } - if (err == 0) { - l = (i < 18) ? i + 6 : i - 18 + 6; - itv->vbi.sliced_dec_data[line].line = l; - itv->vbi.sliced_dec_data[line].field = i >= 18; - itv->vbi.sliced_dec_data[line].id = id2; - memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42); - line++; - } - p += 43; - } - while (line < 36) { - itv->vbi.sliced_dec_data[line].id = 0; - itv->vbi.sliced_dec_data[line].line = 0; - itv->vbi.sliced_dec_data[line].field = 0; - line++; - } - return line * sizeof(itv->vbi.sliced_dec_data[0]); -} - -/* Compress raw VBI format, removes leading SAV codes and surplus space after the - field. - Returns new compressed size. */ -static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size) -{ - u32 line_size = itv->vbi.raw_decoder_line_size; - u32 lines = itv->vbi.count; - u8 sav1 = itv->vbi.raw_decoder_sav_odd_field; - u8 sav2 = itv->vbi.raw_decoder_sav_even_field; - u8 *q = buf; - u8 *p; - int i; - - for (i = 0; i < lines; i++) { - p = buf + i * line_size; - - /* Look for SAV code */ - if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) { - break; - } - memcpy(q, p + 4, line_size - 4); - q += line_size - 4; - } - return lines * (line_size - 4); -} - - -/* Compressed VBI format, all found sliced blocks put next to one another - Returns new compressed size */ -static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav) -{ - u32 line_size = itv->vbi.sliced_decoder_line_size; - struct v4l2_decode_vbi_line vbi; - int i; - unsigned lines = 0; - - /* find the first valid line */ - for (i = 0; i < size; i++, buf++) { - if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav) - break; - } - - size -= i; - if (size < line_size) { - return line; - } - for (i = 0; i < size / line_size; i++) { - u8 *p = buf + i * line_size; - - /* Look for SAV code */ - if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) { - continue; - } - vbi.p = p + 4; - v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi); - if (vbi.type && !(lines & (1 << vbi.line))) { - lines |= 1 << vbi.line; - itv->vbi.sliced_data[line].id = vbi.type; - itv->vbi.sliced_data[line].field = vbi.is_second_field; - itv->vbi.sliced_data[line].line = vbi.line; - memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42); - line++; - } - } - return line; -} - -void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, - u64 pts_stamp, int streamtype) -{ - u8 *p = (u8 *) buf->buf; - u32 size = buf->bytesused; - int y; - - /* Raw VBI data */ - if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) { - u8 type; - - ivtv_buf_swap(buf); - - type = p[3]; - - size = buf->bytesused = compress_raw_buf(itv, p, size); - - /* second field of the frame? */ - if (type == itv->vbi.raw_decoder_sav_even_field) { - /* Dirty hack needed for backwards - compatibility of old VBI software. */ - p += size - 4; - memcpy(p, &itv->vbi.frame, 4); - itv->vbi.frame++; - } - return; - } - - /* Sliced VBI data with data insertion */ - if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) { - int lines; - - ivtv_buf_swap(buf); - - /* first field */ - lines = compress_sliced_buf(itv, 0, p, size / 2, - itv->vbi.sliced_decoder_sav_odd_field); - /* second field */ - /* experimentation shows that the second half does not always begin - at the exact address. So start a bit earlier (hence 32). */ - lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32, - itv->vbi.sliced_decoder_sav_even_field); - /* always return at least one empty line */ - if (lines == 0) { - itv->vbi.sliced_data[0].id = 0; - itv->vbi.sliced_data[0].line = 0; - itv->vbi.sliced_data[0].field = 0; - lines = 1; - } - buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]); - memcpy(p, &itv->vbi.sliced_data[0], size); - - if (itv->vbi.insert_mpeg) { - copy_vbi_data(itv, lines, pts_stamp); - } - itv->vbi.frame++; - return; - } - - /* Sliced VBI re-inserted from an MPEG stream */ - if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { - /* If the size is not 4-byte aligned, then the starting address - for the swapping is also shifted. After swapping the data the - real start address of the VBI data is exactly 4 bytes after the - original start. It's a bit fiddly but it works like a charm. - Non-4-byte alignment happens when an lseek is done on the input - mpeg file to a non-4-byte aligned position. So on arrival here - the VBI data is also non-4-byte aligned. */ - int offset = size & 3; - int cnt; - - if (offset) { - p += 4 - offset; - } - /* Swap Buffer */ - for (y = 0; y < size; y += 4) { - swab32s((u32 *)(p + y)); - } - - cnt = ivtv_convert_ivtv_vbi(itv, p + offset); - memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt); - buf->bytesused = cnt; - - ivtv_write_vbi(itv, itv->vbi.sliced_dec_data, - cnt / sizeof(itv->vbi.sliced_dec_data[0])); - return; - } -} - -void ivtv_disable_cc(struct ivtv *itv) -{ - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - - clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); - ivtv_set_cc(itv, 0, &cc); - itv->vbi.cc_payload_idx = 0; -} - - -void ivtv_vbi_work_handler(struct ivtv *itv) -{ - struct vbi_info *vi = &itv->vbi; - struct v4l2_sliced_vbi_data data; - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - - /* Lock */ - if (itv->output_mode == OUT_PASSTHROUGH) { - if (itv->is_50hz) { - data.id = V4L2_SLICED_WSS_625; - data.field = 0; - - if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { - ivtv_set_wss(itv, 1, data.data[0] & 0xf); - vi->wss_missing_cnt = 0; - } else if (vi->wss_missing_cnt == 4) { - ivtv_set_wss(itv, 1, 0x8); /* 4x3 full format */ - } else { - vi->wss_missing_cnt++; - } - } - else { - int mode = 0; - - data.id = V4L2_SLICED_CAPTION_525; - data.field = 0; - if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { - mode |= 1; - cc.odd[0] = data.data[0]; - cc.odd[1] = data.data[1]; - } - data.field = 1; - if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) { - mode |= 2; - cc.even[0] = data.data[0]; - cc.even[1] = data.data[1]; - } - if (mode) { - vi->cc_missing_cnt = 0; - ivtv_set_cc(itv, mode, &cc); - } else if (vi->cc_missing_cnt == 4) { - ivtv_set_cc(itv, 0, &cc); - } else { - vi->cc_missing_cnt++; - } - } - return; - } - - if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) { - ivtv_set_wss(itv, 1, vi->wss_payload & 0xf); - } - - if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) { - if (vi->cc_payload_idx == 0) { - clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); - ivtv_set_cc(itv, 3, &cc); - } - while (vi->cc_payload_idx) { - cc = vi->cc_payload[0]; - - memcpy(vi->cc_payload, vi->cc_payload + 1, - sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0])); - vi->cc_payload_idx--; - if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80) - continue; - - ivtv_set_cc(itv, 3, &cc); - break; - } - } - - if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) { - ivtv_set_vps(itv, 1); - } -} diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h deleted file mode 100644 index 166dd0b75d0f..000000000000 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Vertical Blank Interval support functions - Copyright (C) 2004-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_VBI_H -#define IVTV_VBI_H - -ssize_t -ivtv_write_vbi_from_user(struct ivtv *itv, - const struct v4l2_sliced_vbi_data __user *sliced, - size_t count); -void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, - u64 pts_stamp, int streamtype); -int ivtv_used_line(struct ivtv *itv, int line, int field); -void ivtv_disable_cc(struct ivtv *itv); -void ivtv_set_vbi(unsigned long arg); -void ivtv_vbi_work_handler(struct ivtv *itv); - -#endif diff --git a/drivers/media/video/ivtv/ivtv-version.h b/drivers/media/video/ivtv/ivtv-version.h deleted file mode 100644 index a20f346fcad8..000000000000 --- a/drivers/media/video/ivtv/ivtv-version.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - ivtv driver version information - Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_VERSION_H -#define IVTV_VERSION_H - -#define IVTV_DRIVER_NAME "ivtv" -#define IVTV_VERSION "1.4.3" - -#endif diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c deleted file mode 100644 index 2ad65eb29832..000000000000 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ /dev/null @@ -1,1296 +0,0 @@ -/* - yuv support - - Copyright (C) 2007 Ian Armstrong <ian@iarmst.demon.co.uk> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ivtv-driver.h" -#include "ivtv-udma.h" -#include "ivtv-yuv.h" - -/* YUV buffer offsets */ -const u32 yuv_offset[IVTV_YUV_BUFFERS] = { - 0x001a8600, - 0x00240400, - 0x002d8200, - 0x00370000, - 0x00029000, - 0x000C0E00, - 0x006B0400, - 0x00748200 -}; - -static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma, - struct ivtv_dma_frame *args) -{ - struct ivtv_dma_page_info y_dma; - struct ivtv_dma_page_info uv_dma; - struct yuv_playback_info *yi = &itv->yuv_info; - u8 frame = yi->draw_frame; - struct yuv_frame_info *f = &yi->new_frame_info[frame]; - int i; - int y_pages, uv_pages; - unsigned long y_buffer_offset, uv_buffer_offset; - int y_decode_height, uv_decode_height, y_size; - - y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame]; - uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET; - - y_decode_height = uv_decode_height = f->src_h + f->src_y; - - if (f->offset_y) - y_buffer_offset += 720 * 16; - - if (y_decode_height & 15) - y_decode_height = (y_decode_height + 16) & ~15; - - if (uv_decode_height & 31) - uv_decode_height = (uv_decode_height + 32) & ~31; - - y_size = 720 * y_decode_height; - - /* Still in USE */ - if (dma->SG_length || dma->page_count) { - IVTV_DEBUG_WARN - ("prep_user_dma: SG_length %d page_count %d still full?\n", - dma->SG_length, dma->page_count); - return -EBUSY; - } - - ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height); - ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height); - - /* Get user pages for DMA Xfer */ - down_read(¤t->mm->mmap_sem); - y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL); - uv_pages = 0; /* silence gcc. value is set and consumed only if: */ - if (y_pages == y_dma.page_count) { - uv_pages = get_user_pages(current, current->mm, - uv_dma.uaddr, uv_dma.page_count, 0, 1, - &dma->map[y_pages], NULL); - } - up_read(¤t->mm->mmap_sem); - - if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) { - int rc = -EFAULT; - - if (y_pages == y_dma.page_count) { - IVTV_DEBUG_WARN - ("failed to map uv user pages, returned %d " - "expecting %d\n", uv_pages, uv_dma.page_count); - - if (uv_pages >= 0) { - for (i = 0; i < uv_pages; i++) - put_page(dma->map[y_pages + i]); - rc = -EFAULT; - } else { - rc = uv_pages; - } - } else { - IVTV_DEBUG_WARN - ("failed to map y user pages, returned %d " - "expecting %d\n", y_pages, y_dma.page_count); - } - if (y_pages >= 0) { - for (i = 0; i < y_pages; i++) - put_page(dma->map[i]); - /* - * Inherit the -EFAULT from rc's - * initialization, but allow it to be - * overriden by uv_pages above if it was an - * actual errno. - */ - } else { - rc = y_pages; - } - return rc; - } - - dma->page_count = y_pages + uv_pages; - - /* Fill & map SG List */ - if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) { - IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n"); - for (i = 0; i < dma->page_count; i++) { - put_page(dma->map[i]); - } - dma->page_count = 0; - return -ENOMEM; - } - dma->SG_length = pci_map_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE); - - /* Fill SG Array with new values */ - ivtv_udma_fill_sg_array(dma, y_buffer_offset, uv_buffer_offset, y_size); - - /* If we've offset the y plane, ensure top area is blanked */ - if (f->offset_y && yi->blanking_dmaptr) { - dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16); - dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr); - dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]); - dma->SG_length++; - } - - /* Tag SG Array with Interrupt Bit */ - dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000); - - ivtv_udma_sync_for_device(itv); - return 0; -} - -/* We rely on a table held in the firmware - Quick check. */ -int ivtv_yuv_filter_check(struct ivtv *itv) -{ - int i, y, uv; - - for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) { - if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) || - (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) { - IVTV_WARN ("YUV filter table not found in firmware.\n"); - return -1; - } - } - return 0; -} - -static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2) -{ - u32 i, line; - - /* If any filter is -1, then don't update it */ - if (h_filter > -1) { - if (h_filter > 4) - h_filter = 4; - i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384); - for (line = 0; line < 16; line++) { - write_reg(read_dec(i), 0x02804); - write_reg(read_dec(i), 0x0281c); - i += 4; - write_reg(read_dec(i), 0x02808); - write_reg(read_dec(i), 0x02820); - i += 4; - write_reg(read_dec(i), 0x0280c); - write_reg(read_dec(i), 0x02824); - i += 4; - write_reg(read_dec(i), 0x02810); - write_reg(read_dec(i), 0x02828); - i += 4; - write_reg(read_dec(i), 0x02814); - write_reg(read_dec(i), 0x0282c); - i += 8; - write_reg(0, 0x02818); - write_reg(0, 0x02830); - } - IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter); - } - - if (v_filter_1 > -1) { - if (v_filter_1 > 4) - v_filter_1 = 4; - i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192); - for (line = 0; line < 16; line++) { - write_reg(read_dec(i), 0x02900); - i += 4; - write_reg(read_dec(i), 0x02904); - i += 8; - write_reg(0, 0x02908); - } - IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1); - } - - if (v_filter_2 > -1) { - if (v_filter_2 > 4) - v_filter_2 = 4; - i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192); - for (line = 0; line < 16; line++) { - write_reg(read_dec(i), 0x0290c); - i += 4; - write_reg(read_dec(i), 0x02910); - i += 8; - write_reg(0, 0x02914); - } - IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2); - } -} - -static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - u32 reg_2834, reg_2838, reg_283c; - u32 reg_2844, reg_2854, reg_285c; - u32 reg_2864, reg_2874, reg_2890; - u32 reg_2870, reg_2870_base, reg_2870_offset; - int x_cutoff; - int h_filter; - u32 master_width; - - IVTV_DEBUG_WARN - ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n", - f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x); - - /* How wide is the src image */ - x_cutoff = f->src_w + f->src_x; - - /* Set the display width */ - reg_2834 = f->dst_w; - reg_2838 = reg_2834; - - /* Set the display position */ - reg_2890 = f->dst_x; - - /* Index into the image horizontally */ - reg_2870 = 0; - - /* 2870 is normally fudged to align video coords with osd coords. - If running full screen, it causes an unwanted left shift - Remove the fudge if we almost fill the screen. - Gradually adjust the offset to avoid the video 'snapping' - left/right if it gets dragged through this region. - Only do this if osd is full width. */ - if (f->vis_w == 720) { - if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680)) - reg_2870 = 10 - (f->tru_x - f->pan_x) / 4; - else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660)) - reg_2870 = (10 + (f->tru_x - f->pan_x) / 2); - - if (f->dst_w >= f->src_w) - reg_2870 = reg_2870 << 16 | reg_2870; - else - reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1); - } - - if (f->dst_w < f->src_w) - reg_2870 = 0x000d000e - reg_2870; - else - reg_2870 = 0x0012000e - reg_2870; - - /* We're also using 2870 to shift the image left (src_x & negative dst_x) */ - reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19; - - if (f->dst_w >= f->src_w) { - x_cutoff &= ~1; - master_width = (f->src_w * 0x00200000) / (f->dst_w); - if (master_width * f->dst_w != f->src_w * 0x00200000) - master_width++; - reg_2834 = (reg_2834 << 16) | x_cutoff; - reg_2838 = (reg_2838 << 16) | x_cutoff; - reg_283c = master_width >> 2; - reg_2844 = master_width >> 2; - reg_2854 = master_width; - reg_285c = master_width >> 1; - reg_2864 = master_width >> 1; - - /* We also need to factor in the scaling - (src_w - dst_w) / (src_w / 4) */ - if (f->dst_w > f->src_w) - reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14); - else - reg_2870_base = 0; - - reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base); - reg_2874 = 0; - } else if (f->dst_w < f->src_w / 2) { - master_width = (f->src_w * 0x00080000) / f->dst_w; - if (master_width * f->dst_w != f->src_w * 0x00080000) - master_width++; - reg_2834 = (reg_2834 << 16) | x_cutoff; - reg_2838 = (reg_2838 << 16) | x_cutoff; - reg_283c = master_width >> 2; - reg_2844 = master_width >> 1; - reg_2854 = master_width; - reg_285c = master_width >> 1; - reg_2864 = master_width >> 1; - reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset; - reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16; - reg_2874 = 0x00000012; - } else { - master_width = (f->src_w * 0x00100000) / f->dst_w; - if (master_width * f->dst_w != f->src_w * 0x00100000) - master_width++; - reg_2834 = (reg_2834 << 16) | x_cutoff; - reg_2838 = (reg_2838 << 16) | x_cutoff; - reg_283c = master_width >> 2; - reg_2844 = master_width >> 1; - reg_2854 = master_width; - reg_285c = master_width >> 1; - reg_2864 = master_width >> 1; - reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1; - reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16; - reg_2874 = 0x00000001; - } - - /* Select the horizontal filter */ - if (f->src_w == f->dst_w) { - /* An exact size match uses filter 0 */ - h_filter = 0; - } else { - /* Figure out which filter to use */ - h_filter = ((f->src_w << 16) / f->dst_w) >> 15; - h_filter = (h_filter >> 1) + (h_filter & 1); - /* Only an exact size match can use filter 0 */ - h_filter += !h_filter; - } - - write_reg(reg_2834, 0x02834); - write_reg(reg_2838, 0x02838); - IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n", - yi->reg_2834, reg_2834, yi->reg_2838, reg_2838); - - write_reg(reg_283c, 0x0283c); - write_reg(reg_2844, 0x02844); - - IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n", - yi->reg_283c, reg_283c, yi->reg_2844, reg_2844); - - write_reg(0x00080514, 0x02840); - write_reg(0x00100514, 0x02848); - IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n", - yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514); - - write_reg(reg_2854, 0x02854); - IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n", - yi->reg_2854, reg_2854); - - write_reg(reg_285c, 0x0285c); - write_reg(reg_2864, 0x02864); - IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n", - yi->reg_285c, reg_285c, yi->reg_2864, reg_2864); - - write_reg(reg_2874, 0x02874); - IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n", - yi->reg_2874, reg_2874); - - write_reg(reg_2870, 0x02870); - IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n", - yi->reg_2870, reg_2870); - - write_reg(reg_2890, 0x02890); - IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n", - yi->reg_2890, reg_2890); - - /* Only update the filter if we really need to */ - if (h_filter != yi->h_filter) { - ivtv_yuv_filter(itv, h_filter, -1, -1); - yi->h_filter = h_filter; - } -} - -static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - u32 master_height; - u32 reg_2918, reg_291c, reg_2920, reg_2928; - u32 reg_2930, reg_2934, reg_293c; - u32 reg_2940, reg_2944, reg_294c; - u32 reg_2950, reg_2954, reg_2958, reg_295c; - u32 reg_2960, reg_2964, reg_2968, reg_296c; - u32 reg_289c; - u32 src_major_y, src_minor_y; - u32 src_major_uv, src_minor_uv; - u32 reg_2964_base, reg_2968_base; - int v_filter_1, v_filter_2; - - IVTV_DEBUG_WARN - ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n", - f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y); - - /* What scaling mode is being used... */ - IVTV_DEBUG_YUV("Scaling mode Y: %s\n", - f->interlaced_y ? "Interlaced" : "Progressive"); - - IVTV_DEBUG_YUV("Scaling mode UV: %s\n", - f->interlaced_uv ? "Interlaced" : "Progressive"); - - /* What is the source video being treated as... */ - IVTV_DEBUG_WARN("Source video: %s\n", - f->interlaced ? "Interlaced" : "Progressive"); - - /* We offset into the image using two different index methods, so split - the y source coord into two parts. */ - if (f->src_y < 8) { - src_minor_uv = f->src_y; - src_major_uv = 0; - } else { - src_minor_uv = 8; - src_major_uv = f->src_y - 8; - } - - src_minor_y = src_minor_uv; - src_major_y = src_major_uv; - - if (f->offset_y) - src_minor_y += 16; - - if (f->interlaced_y) - reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y); - else - reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1); - - if (f->interlaced_uv) - reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1); - else - reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv); - - reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14; - reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14; - - if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) { - master_height = (f->src_h * 0x00400000) / f->dst_h; - if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2) - master_height++; - reg_2920 = master_height >> 2; - reg_2928 = master_height >> 3; - reg_2930 = master_height; - reg_2940 = master_height >> 1; - reg_2964_base >>= 3; - reg_2968_base >>= 3; - reg_296c = 0x00000000; - } else if (f->dst_h >= f->src_h) { - master_height = (f->src_h * 0x00400000) / f->dst_h; - master_height = (master_height >> 1) + (master_height & 1); - reg_2920 = master_height >> 2; - reg_2928 = master_height >> 2; - reg_2930 = master_height; - reg_2940 = master_height >> 1; - reg_296c = 0x00000000; - if (f->interlaced_y) { - reg_2964_base >>= 3; - } else { - reg_296c++; - reg_2964_base >>= 2; - } - if (f->interlaced_uv) - reg_2928 >>= 1; - reg_2968_base >>= 3; - } else if (f->dst_h >= f->src_h / 2) { - master_height = (f->src_h * 0x00200000) / f->dst_h; - master_height = (master_height >> 1) + (master_height & 1); - reg_2920 = master_height >> 2; - reg_2928 = master_height >> 2; - reg_2930 = master_height; - reg_2940 = master_height; - reg_296c = 0x00000101; - if (f->interlaced_y) { - reg_2964_base >>= 2; - } else { - reg_296c++; - reg_2964_base >>= 1; - } - if (f->interlaced_uv) - reg_2928 >>= 1; - reg_2968_base >>= 2; - } else { - master_height = (f->src_h * 0x00100000) / f->dst_h; - master_height = (master_height >> 1) + (master_height & 1); - reg_2920 = master_height >> 2; - reg_2928 = master_height >> 2; - reg_2930 = master_height; - reg_2940 = master_height; - reg_2964_base >>= 1; - reg_2968_base >>= 2; - reg_296c = 0x00000102; - } - - /* FIXME These registers change depending on scaled / unscaled output - We really need to work out what they should be */ - if (f->src_h == f->dst_h) { - reg_2934 = 0x00020000; - reg_293c = 0x00100000; - reg_2944 = 0x00040000; - reg_294c = 0x000b0000; - } else { - reg_2934 = 0x00000FF0; - reg_293c = 0x00000FF0; - reg_2944 = 0x00000FF0; - reg_294c = 0x00000FF0; - } - - /* The first line to be displayed */ - reg_2950 = 0x00010000 + src_major_y; - if (f->interlaced_y) - reg_2950 += 0x00010000; - reg_2954 = reg_2950 + 1; - - reg_2958 = 0x00010000 + (src_major_y >> 1); - if (f->interlaced_uv) - reg_2958 += 0x00010000; - reg_295c = reg_2958 + 1; - - if (yi->decode_height == 480) - reg_289c = 0x011e0017; - else - reg_289c = 0x01500017; - - if (f->dst_y < 0) - reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1); - else - reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1); - - /* How much of the source to decode. - Take into account the source offset */ - reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) | - (((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15); - - /* Calculate correct value for register 2964 */ - if (f->src_h == f->dst_h) { - reg_2964 = 1; - } else { - reg_2964 = 2 + ((f->dst_h << 1) / f->src_h); - reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1); - } - reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1); - reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94); - - /* Okay, we've wasted time working out the correct value, - but if we use it, it fouls the the window alignment. - Fudge it to what we want... */ - reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16)); - reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16)); - - /* Deviate further from what it should be. I find the flicker headache - inducing so try to reduce it slightly. Leave 2968 as-is otherwise - colours foul. */ - if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h)) - reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2); - - if (!f->interlaced_y) - reg_2964 -= 0x00010001; - if (!f->interlaced_uv) - reg_2968 -= 0x00010001; - - reg_2964 += ((reg_2964_base << 16) | reg_2964_base); - reg_2968 += ((reg_2968_base << 16) | reg_2968_base); - - /* Select the vertical filter */ - if (f->src_h == f->dst_h) { - /* An exact size match uses filter 0/1 */ - v_filter_1 = 0; - v_filter_2 = 1; - } else { - /* Figure out which filter to use */ - v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15; - v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1); - /* Only an exact size match can use filter 0 */ - v_filter_1 += !v_filter_1; - v_filter_2 = v_filter_1; - } - - write_reg(reg_2934, 0x02934); - write_reg(reg_293c, 0x0293c); - IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n", - yi->reg_2934, reg_2934, yi->reg_293c, reg_293c); - write_reg(reg_2944, 0x02944); - write_reg(reg_294c, 0x0294c); - IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n", - yi->reg_2944, reg_2944, yi->reg_294c, reg_294c); - - /* Ensure 2970 is 0 (does it ever change ?) */ -/* write_reg(0,0x02970); */ -/* IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */ - - write_reg(reg_2930, 0x02938); - write_reg(reg_2930, 0x02930); - IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n", - yi->reg_2930, reg_2930, yi->reg_2938, reg_2930); - - write_reg(reg_2928, 0x02928); - write_reg(reg_2928 + 0x514, 0x0292C); - IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n", - yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514); - - write_reg(reg_2920, 0x02920); - write_reg(reg_2920 + 0x514, 0x02924); - IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n", - yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514); - - write_reg(reg_2918, 0x02918); - write_reg(reg_291c, 0x0291C); - IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n", - yi->reg_2918, reg_2918, yi->reg_291c, reg_291c); - - write_reg(reg_296c, 0x0296c); - IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n", - yi->reg_296c, reg_296c); - - write_reg(reg_2940, 0x02948); - write_reg(reg_2940, 0x02940); - IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n", - yi->reg_2940, reg_2940, yi->reg_2948, reg_2940); - - write_reg(reg_2950, 0x02950); - write_reg(reg_2954, 0x02954); - IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n", - yi->reg_2950, reg_2950, yi->reg_2954, reg_2954); - - write_reg(reg_2958, 0x02958); - write_reg(reg_295c, 0x0295C); - IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n", - yi->reg_2958, reg_2958, yi->reg_295c, reg_295c); - - write_reg(reg_2960, 0x02960); - IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n", - yi->reg_2960, reg_2960); - - write_reg(reg_2964, 0x02964); - write_reg(reg_2968, 0x02968); - IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n", - yi->reg_2964, reg_2964, yi->reg_2968, reg_2968); - - write_reg(reg_289c, 0x0289c); - IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n", - yi->reg_289c, reg_289c); - - /* Only update filter 1 if we really need to */ - if (v_filter_1 != yi->v_filter_1) { - ivtv_yuv_filter(itv, -1, v_filter_1, -1); - yi->v_filter_1 = v_filter_1; - } - - /* Only update filter 2 if we really need to */ - if (v_filter_2 != yi->v_filter_2) { - ivtv_yuv_filter(itv, -1, -1, v_filter_2); - yi->v_filter_2 = v_filter_2; - } -} - -/* Modify the supplied coordinate information to fit the visible osd area */ -static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f) -{ - struct yuv_frame_info *of = &itv->yuv_info.old_frame_info; - int osd_crop; - u32 osd_scale; - u32 yuv_update = 0; - - /* Sorry, but no negative coords for src */ - if (f->src_x < 0) - f->src_x = 0; - if (f->src_y < 0) - f->src_y = 0; - - /* Can only reduce width down to 1/4 original size */ - if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) { - f->src_x += osd_crop / 2; - f->src_w = (f->src_w - osd_crop) & ~3; - f->dst_w = f->src_w / 4; - f->dst_w += f->dst_w & 1; - } - - /* Can only reduce height down to 1/4 original size */ - if (f->src_h / f->dst_h >= 2) { - /* Overflow may be because we're running progressive, - so force mode switch */ - f->interlaced_y = 1; - /* Make sure we're still within limits for interlace */ - if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) { - /* If we reach here we'll have to force the height. */ - f->src_y += osd_crop / 2; - f->src_h = (f->src_h - osd_crop) & ~3; - f->dst_h = f->src_h / 4; - f->dst_h += f->dst_h & 1; - } - } - - /* If there's nothing to safe to display, we may as well stop now */ - if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 || - (int)f->src_w <= 2 || (int)f->src_h <= 2) { - return IVTV_YUV_UPDATE_INVALID; - } - - /* Ensure video remains inside OSD area */ - osd_scale = (f->src_h << 16) / f->dst_h; - - if ((osd_crop = f->pan_y - f->dst_y) > 0) { - /* Falls off the upper edge - crop */ - f->src_y += (osd_scale * osd_crop) >> 16; - f->src_h -= (osd_scale * osd_crop) >> 16; - f->dst_h -= osd_crop; - f->dst_y = 0; - } else { - f->dst_y -= f->pan_y; - } - - if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) { - /* Falls off the lower edge - crop */ - f->dst_h -= osd_crop; - f->src_h -= (osd_scale * osd_crop) >> 16; - } - - osd_scale = (f->src_w << 16) / f->dst_w; - - if ((osd_crop = f->pan_x - f->dst_x) > 0) { - /* Fall off the left edge - crop */ - f->src_x += (osd_scale * osd_crop) >> 16; - f->src_w -= (osd_scale * osd_crop) >> 16; - f->dst_w -= osd_crop; - f->dst_x = 0; - } else { - f->dst_x -= f->pan_x; - } - - if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) { - /* Falls off the right edge - crop */ - f->dst_w -= osd_crop; - f->src_w -= (osd_scale * osd_crop) >> 16; - } - - if (itv->yuv_info.track_osd) { - /* The OSD can be moved. Track to it */ - f->dst_x += itv->yuv_info.osd_x_offset; - f->dst_y += itv->yuv_info.osd_y_offset; - } - - /* Width & height for both src & dst must be even. - Same for coordinates. */ - f->dst_w &= ~1; - f->dst_x &= ~1; - - f->src_w += f->src_x & 1; - f->src_x &= ~1; - - f->src_w &= ~1; - f->dst_w &= ~1; - - f->dst_h &= ~1; - f->dst_y &= ~1; - - f->src_h += f->src_y & 1; - f->src_y &= ~1; - - f->src_h &= ~1; - f->dst_h &= ~1; - - /* Due to rounding, we may have reduced the output size to <1/4 of - the source. Check again, but this time just resize. Don't change - source coordinates */ - if (f->dst_w < f->src_w / 4) { - f->src_w &= ~3; - f->dst_w = f->src_w / 4; - f->dst_w += f->dst_w & 1; - } - if (f->dst_h < f->src_h / 4) { - f->src_h &= ~3; - f->dst_h = f->src_h / 4; - f->dst_h += f->dst_h & 1; - } - - /* Check again. If there's nothing to safe to display, stop now */ - if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 || - (int)f->src_w <= 2 || (int)f->src_h <= 2) { - return IVTV_YUV_UPDATE_INVALID; - } - - /* Both x offset & width are linked, so they have to be done together */ - if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) || - (of->dst_x != f->dst_x) || (of->src_x != f->src_x) || - (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) { - yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL; - } - - if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) || - (of->dst_y != f->dst_y) || (of->src_y != f->src_y) || - (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) || - (of->lace_mode != f->lace_mode) || - (of->interlaced_y != f->interlaced_y) || - (of->interlaced_uv != f->interlaced_uv)) { - yuv_update |= IVTV_YUV_UPDATE_VERTICAL; - } - - return yuv_update; -} - -/* Update the scaling register to the requested value */ -void ivtv_yuv_work_handler(struct ivtv *itv) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - struct yuv_frame_info f; - int frame = yi->update_frame; - u32 yuv_update; - - IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame); - f = yi->new_frame_info[frame]; - - if (yi->track_osd) { - /* Snapshot the osd pan info */ - f.pan_x = yi->osd_x_pan; - f.pan_y = yi->osd_y_pan; - f.vis_w = yi->osd_vis_w; - f.vis_h = yi->osd_vis_h; - } else { - /* Not tracking the osd, so assume full screen */ - f.pan_x = 0; - f.pan_y = 0; - f.vis_w = 720; - f.vis_h = yi->decode_height; - } - - /* Calculate the display window coordinates. Exit if nothing left */ - if (!(yuv_update = ivtv_yuv_window_setup(itv, &f))) - return; - - if (yuv_update & IVTV_YUV_UPDATE_INVALID) { - write_reg(0x01008080, 0x2898); - } else if (yuv_update) { - write_reg(0x00108080, 0x2898); - - if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL) - ivtv_yuv_handle_horizontal(itv, &f); - - if (yuv_update & IVTV_YUV_UPDATE_VERTICAL) - ivtv_yuv_handle_vertical(itv, &f); - } - yi->old_frame_info = f; -} - -static void ivtv_yuv_init(struct ivtv *itv) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - - IVTV_DEBUG_YUV("ivtv_yuv_init\n"); - - /* Take a snapshot of the current register settings */ - yi->reg_2834 = read_reg(0x02834); - yi->reg_2838 = read_reg(0x02838); - yi->reg_283c = read_reg(0x0283c); - yi->reg_2840 = read_reg(0x02840); - yi->reg_2844 = read_reg(0x02844); - yi->reg_2848 = read_reg(0x02848); - yi->reg_2854 = read_reg(0x02854); - yi->reg_285c = read_reg(0x0285c); - yi->reg_2864 = read_reg(0x02864); - yi->reg_2870 = read_reg(0x02870); - yi->reg_2874 = read_reg(0x02874); - yi->reg_2898 = read_reg(0x02898); - yi->reg_2890 = read_reg(0x02890); - - yi->reg_289c = read_reg(0x0289c); - yi->reg_2918 = read_reg(0x02918); - yi->reg_291c = read_reg(0x0291c); - yi->reg_2920 = read_reg(0x02920); - yi->reg_2924 = read_reg(0x02924); - yi->reg_2928 = read_reg(0x02928); - yi->reg_292c = read_reg(0x0292c); - yi->reg_2930 = read_reg(0x02930); - yi->reg_2934 = read_reg(0x02934); - yi->reg_2938 = read_reg(0x02938); - yi->reg_293c = read_reg(0x0293c); - yi->reg_2940 = read_reg(0x02940); - yi->reg_2944 = read_reg(0x02944); - yi->reg_2948 = read_reg(0x02948); - yi->reg_294c = read_reg(0x0294c); - yi->reg_2950 = read_reg(0x02950); - yi->reg_2954 = read_reg(0x02954); - yi->reg_2958 = read_reg(0x02958); - yi->reg_295c = read_reg(0x0295c); - yi->reg_2960 = read_reg(0x02960); - yi->reg_2964 = read_reg(0x02964); - yi->reg_2968 = read_reg(0x02968); - yi->reg_296c = read_reg(0x0296c); - yi->reg_2970 = read_reg(0x02970); - - yi->v_filter_1 = -1; - yi->v_filter_2 = -1; - yi->h_filter = -1; - - /* Set some valid size info */ - yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF; - yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF; - - /* Bit 2 of reg 2878 indicates current decoder output format - 0 : NTSC 1 : PAL */ - if (read_reg(0x2878) & 4) - yi->decode_height = 576; - else - yi->decode_height = 480; - - if (!itv->osd_info) { - yi->osd_vis_w = 720 - yi->osd_x_offset; - yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; - } else { - /* If no visible size set, assume full size */ - if (!yi->osd_vis_w) - yi->osd_vis_w = 720 - yi->osd_x_offset; - - if (!yi->osd_vis_h) { - yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; - } else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) { - /* If output video standard has changed, requested height may - not be legal */ - IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n", - yi->osd_vis_h + yi->osd_y_offset, - yi->decode_height); - yi->osd_vis_h = yi->decode_height - yi->osd_y_offset; - } - } - - /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ - yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); - if (yi->blanking_ptr) { - yi->blanking_dmaptr = pci_map_single(itv->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); - } else { - yi->blanking_dmaptr = 0; - IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n"); - } - - /* Enable YUV decoder output */ - write_reg_sync(0x01, IVTV_REG_VDM); - - set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); - atomic_set(&yi->next_dma_frame, 0); -} - -/* Get next available yuv buffer on PVR350 */ -static void ivtv_yuv_next_free(struct ivtv *itv) -{ - int draw, display; - struct yuv_playback_info *yi = &itv->yuv_info; - - if (atomic_read(&yi->next_dma_frame) == -1) - ivtv_yuv_init(itv); - - draw = atomic_read(&yi->next_fill_frame); - display = atomic_read(&yi->next_dma_frame); - - if (display > draw) - display -= IVTV_YUV_BUFFERS; - - if (draw - display >= yi->max_frames_buffered) - draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS; - else - yi->new_frame_info[draw].update = 0; - - yi->draw_frame = draw; -} - -/* Set up frame according to ivtv_dma_frame parameters */ -static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - u8 frame = yi->draw_frame; - u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS; - struct yuv_frame_info *nf = &yi->new_frame_info[frame]; - struct yuv_frame_info *of = &yi->new_frame_info[last_frame]; - int lace_threshold = yi->lace_threshold; - - /* Preserve old update flag in case we're overwriting a queued frame */ - int update = nf->update; - - /* Take a snapshot of the yuv coordinate information */ - nf->src_x = args->src.left; - nf->src_y = args->src.top; - nf->src_w = args->src.width; - nf->src_h = args->src.height; - nf->dst_x = args->dst.left; - nf->dst_y = args->dst.top; - nf->dst_w = args->dst.width; - nf->dst_h = args->dst.height; - nf->tru_x = args->dst.left; - nf->tru_w = args->src_width; - nf->tru_h = args->src_height; - - /* Are we going to offset the Y plane */ - nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0; - - nf->update = 0; - nf->interlaced_y = 0; - nf->interlaced_uv = 0; - nf->delay = 0; - nf->sync_field = 0; - nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK; - - if (lace_threshold < 0) - lace_threshold = yi->decode_height - 1; - - /* Work out the lace settings */ - switch (nf->lace_mode) { - case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */ - nf->interlaced = 0; - if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021)) - nf->interlaced_y = 0; - else - nf->interlaced_y = 1; - - if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2)) - nf->interlaced_uv = 0; - else - nf->interlaced_uv = 1; - break; - - case IVTV_YUV_MODE_AUTO: - if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) { - nf->interlaced = 0; - if ((nf->tru_h < 512) || - (nf->tru_h > 576 && nf->tru_h < 1021) || - (nf->tru_w > 720 && nf->tru_h < 1021)) - nf->interlaced_y = 0; - else - nf->interlaced_y = 1; - if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2)) - nf->interlaced_uv = 0; - else - nf->interlaced_uv = 1; - } else { - nf->interlaced = 1; - nf->interlaced_y = 1; - nf->interlaced_uv = 1; - } - break; - - case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */ - default: - nf->interlaced = 1; - nf->interlaced_y = 1; - nf->interlaced_uv = 1; - break; - } - - if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) { - yi->old_frame_info_args = *nf; - nf->update = 1; - IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame); - } - - nf->update |= update; - nf->sync_field = yi->lace_sync_field; - nf->delay = nf->sync_field != of->sync_field; -} - -/* Frame is complete & ready for display */ -void ivtv_yuv_frame_complete(struct ivtv *itv) -{ - atomic_set(&itv->yuv_info.next_fill_frame, - (itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS); -} - -static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args) -{ - DEFINE_WAIT(wait); - int rc = 0; - int got_sig = 0; - /* DMA the frame */ - mutex_lock(&itv->udma.lock); - - if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) { - mutex_unlock(&itv->udma.lock); - return rc; - } - - ivtv_udma_prepare(itv); - prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - /* if no UDMA is pending and no UDMA is in progress, then the DMA - is finished */ - while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || - test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { - /* don't interrupt if the DMA is in progress but break off - a still pending DMA. */ - got_sig = signal_pending(current); - if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) - break; - got_sig = 0; - schedule(); - } - finish_wait(&itv->dma_waitq, &wait); - - /* Unmap Last DMA Xfer */ - ivtv_udma_unmap(itv); - - if (got_sig) { - IVTV_DEBUG_INFO("User stopped YUV UDMA\n"); - mutex_unlock(&itv->udma.lock); - return -EINTR; - } - - ivtv_yuv_frame_complete(itv); - - mutex_unlock(&itv->udma.lock); - return rc; -} - -/* Setup frame according to V4L2 parameters */ -void ivtv_yuv_setup_stream_frame(struct ivtv *itv) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - struct ivtv_dma_frame dma_args; - - ivtv_yuv_next_free(itv); - - /* Copy V4L2 parameters to an ivtv_dma_frame struct... */ - dma_args.y_source = NULL; - dma_args.uv_source = NULL; - dma_args.src.left = 0; - dma_args.src.top = 0; - dma_args.src.width = yi->v4l2_src_w; - dma_args.src.height = yi->v4l2_src_h; - dma_args.dst = yi->main_rect; - dma_args.src_width = yi->v4l2_src_w; - dma_args.src_height = yi->v4l2_src_h; - - /* ... and use the same setup routine as ivtv_yuv_prep_frame */ - ivtv_yuv_setup_frame(itv, &dma_args); - - if (!itv->dma_data_req_offset) - itv->dma_data_req_offset = yuv_offset[yi->draw_frame]; -} - -/* Attempt to dma a frame from a user buffer */ -int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - struct ivtv_dma_frame dma_args; - int res; - - ivtv_yuv_setup_stream_frame(itv); - - /* We only need to supply source addresses for this */ - dma_args.y_source = src; - dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31); - /* Wait for frame DMA. Note that serialize_lock is locked, - so to allow other processes to access the driver while - we are waiting unlock first and later lock again. */ - mutex_unlock(&itv->serialize_lock); - res = ivtv_yuv_udma_frame(itv, &dma_args); - mutex_lock(&itv->serialize_lock); - return res; -} - -/* IVTV_IOC_DMA_FRAME ioctl handler */ -int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args) -{ - int res; - -/* IVTV_DEBUG_INFO("yuv_prep_frame\n"); */ - ivtv_yuv_next_free(itv); - ivtv_yuv_setup_frame(itv, args); - /* Wait for frame DMA. Note that serialize_lock is locked, - so to allow other processes to access the driver while - we are waiting unlock first and later lock again. */ - mutex_unlock(&itv->serialize_lock); - res = ivtv_yuv_udma_frame(itv, args); - mutex_lock(&itv->serialize_lock); - return res; -} - -void ivtv_yuv_close(struct ivtv *itv) -{ - struct yuv_playback_info *yi = &itv->yuv_info; - int h_filter, v_filter_1, v_filter_2; - - IVTV_DEBUG_YUV("ivtv_yuv_close\n"); - mutex_unlock(&itv->serialize_lock); - ivtv_waitq(&itv->vsync_waitq); - mutex_lock(&itv->serialize_lock); - - yi->running = 0; - atomic_set(&yi->next_dma_frame, -1); - atomic_set(&yi->next_fill_frame, 0); - - /* Reset registers we have changed so mpeg playback works */ - - /* If we fully restore this register, the display may remain active. - Restore, but set one bit to blank the video. Firmware will always - clear this bit when needed, so not a problem. */ - write_reg(yi->reg_2898 | 0x01000000, 0x2898); - - write_reg(yi->reg_2834, 0x02834); - write_reg(yi->reg_2838, 0x02838); - write_reg(yi->reg_283c, 0x0283c); - write_reg(yi->reg_2840, 0x02840); - write_reg(yi->reg_2844, 0x02844); - write_reg(yi->reg_2848, 0x02848); - write_reg(yi->reg_2854, 0x02854); - write_reg(yi->reg_285c, 0x0285c); - write_reg(yi->reg_2864, 0x02864); - write_reg(yi->reg_2870, 0x02870); - write_reg(yi->reg_2874, 0x02874); - write_reg(yi->reg_2890, 0x02890); - write_reg(yi->reg_289c, 0x0289c); - - write_reg(yi->reg_2918, 0x02918); - write_reg(yi->reg_291c, 0x0291c); - write_reg(yi->reg_2920, 0x02920); - write_reg(yi->reg_2924, 0x02924); - write_reg(yi->reg_2928, 0x02928); - write_reg(yi->reg_292c, 0x0292c); - write_reg(yi->reg_2930, 0x02930); - write_reg(yi->reg_2934, 0x02934); - write_reg(yi->reg_2938, 0x02938); - write_reg(yi->reg_293c, 0x0293c); - write_reg(yi->reg_2940, 0x02940); - write_reg(yi->reg_2944, 0x02944); - write_reg(yi->reg_2948, 0x02948); - write_reg(yi->reg_294c, 0x0294c); - write_reg(yi->reg_2950, 0x02950); - write_reg(yi->reg_2954, 0x02954); - write_reg(yi->reg_2958, 0x02958); - write_reg(yi->reg_295c, 0x0295c); - write_reg(yi->reg_2960, 0x02960); - write_reg(yi->reg_2964, 0x02964); - write_reg(yi->reg_2968, 0x02968); - write_reg(yi->reg_296c, 0x0296c); - write_reg(yi->reg_2970, 0x02970); - - /* Prepare to restore filters */ - - /* First the horizontal filter */ - if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) { - /* An exact size match uses filter 0 */ - h_filter = 0; - } else { - /* Figure out which filter to use */ - h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15; - h_filter = (h_filter >> 1) + (h_filter & 1); - /* Only an exact size match can use filter 0. */ - h_filter += !h_filter; - } - - /* Now the vertical filter */ - if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) { - /* An exact size match uses filter 0/1 */ - v_filter_1 = 0; - v_filter_2 = 1; - } else { - /* Figure out which filter to use */ - v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15; - v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1); - /* Only an exact size match can use filter 0 */ - v_filter_1 += !v_filter_1; - v_filter_2 = v_filter_1; - } - - /* Now restore the filters */ - ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2); - - /* and clear a few registers */ - write_reg(0, 0x02814); - write_reg(0, 0x0282c); - write_reg(0, 0x02904); - write_reg(0, 0x02910); - - /* Release the blanking buffer */ - if (yi->blanking_ptr) { - kfree(yi->blanking_ptr); - yi->blanking_ptr = NULL; - pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE); - } - - /* Invalidate the old dimension information */ - yi->old_frame_info.src_w = 0; - yi->old_frame_info.src_h = 0; - yi->old_frame_info_args.src_w = 0; - yi->old_frame_info_args.src_h = 0; - - /* All done. */ - clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags); -} diff --git a/drivers/media/video/ivtv/ivtv-yuv.h b/drivers/media/video/ivtv/ivtv-yuv.h deleted file mode 100644 index ca5173fbf006..000000000000 --- a/drivers/media/video/ivtv/ivtv-yuv.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - yuv support - - Copyright (C) 2007 Ian Armstrong <ian@iarmst.demon.co.uk> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef IVTV_YUV_H -#define IVTV_YUV_H - -#define IVTV_YUV_BUFFER_UV_OFFSET 0x65400 /* Offset to UV Buffer */ - -/* Offset to filter table in firmware */ -#define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8 -#define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358 - -#define IVTV_YUV_UPDATE_HORIZONTAL 0x01 -#define IVTV_YUV_UPDATE_VERTICAL 0x02 -#define IVTV_YUV_UPDATE_INVALID 0x04 - -extern const u32 yuv_offset[IVTV_YUV_BUFFERS]; - -int ivtv_yuv_filter_check(struct ivtv *itv); -void ivtv_yuv_setup_stream_frame(struct ivtv *itv); -int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src); -void ivtv_yuv_frame_complete(struct ivtv *itv); -int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args); -void ivtv_yuv_close(struct ivtv *itv); -void ivtv_yuv_work_handler(struct ivtv *itv); - -#endif diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c deleted file mode 100644 index 05b94aa8ba32..000000000000 --- a/drivers/media/video/ivtv/ivtvfb.c +++ /dev/null @@ -1,1317 +0,0 @@ -/* - On Screen Display cx23415 Framebuffer driver - - This module presents the cx23415 OSD (onscreen display) framebuffer memory - as a standard Linux /dev/fb style framebuffer device. The framebuffer has - support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp - mode, there is a choice of a three color depths (12, 15 or 16 bits), but no - local alpha. The colorspace is selectable between rgb & yuv. - Depending on the TV standard configured in the ivtv module at load time, - the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp. - Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL) - or 59.94 (NTSC) - - Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com> - - Derived from drivers/video/vesafb.c - Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> - - 2.6 kernel port: - Copyright (C) 2004 Matthias Badaire - - Copyright (C) 2004 Chris Kennedy <c@groovy.org> - - Copyright (C) 2006 Ian Armstrong <ian@iarmst.demon.co.uk> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fb.h> -#include <linux/ivtvfb.h> -#include <linux/slab.h> - -#ifdef CONFIG_MTRR -#include <asm/mtrr.h> -#endif - -#include "ivtv-driver.h" -#include "ivtv-cards.h" -#include "ivtv-i2c.h" -#include "ivtv-udma.h" -#include "ivtv-mailbox.h" -#include "ivtv-firmware.h" - -/* card parameters */ -static int ivtvfb_card_id = -1; -static int ivtvfb_debug = 0; -static bool osd_laced; -static int osd_depth; -static int osd_upper; -static int osd_left; -static int osd_yres; -static int osd_xres; - -module_param(ivtvfb_card_id, int, 0444); -module_param_named(debug,ivtvfb_debug, int, 0644); -module_param(osd_laced, bool, 0444); -module_param(osd_depth, int, 0444); -module_param(osd_upper, int, 0444); -module_param(osd_left, int, 0444); -module_param(osd_yres, int, 0444); -module_param(osd_xres, int, 0444); - -MODULE_PARM_DESC(ivtvfb_card_id, - "Only use framebuffer of the specified ivtv card (0-31)\n" - "\t\t\tdefault -1: initialize all available framebuffers"); - -MODULE_PARM_DESC(debug, - "Debug level (bitmask). Default: errors only\n" - "\t\t\t(debug = 3 gives full debugging)"); - -/* Why upper, left, xres, yres, depth, laced ? To match terminology used - by fbset. - Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */ - -MODULE_PARM_DESC(osd_laced, - "Interlaced mode\n" - "\t\t\t0=off\n" - "\t\t\t1=on\n" - "\t\t\tdefault off"); - -MODULE_PARM_DESC(osd_depth, - "Bits per pixel - 8, 16, 32\n" - "\t\t\tdefault 8"); - -MODULE_PARM_DESC(osd_upper, - "Vertical start position\n" - "\t\t\tdefault 0 (Centered)"); - -MODULE_PARM_DESC(osd_left, - "Horizontal start position\n" - "\t\t\tdefault 0 (Centered)"); - -MODULE_PARM_DESC(osd_yres, - "Display height\n" - "\t\t\tdefault 480 (PAL)\n" - "\t\t\t 400 (NTSC)"); - -MODULE_PARM_DESC(osd_xres, - "Display width\n" - "\t\t\tdefault 640"); - -MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong"); -MODULE_LICENSE("GPL"); - -/* --------------------------------------------------------------------- */ - -#define IVTVFB_DBGFLG_WARN (1 << 0) -#define IVTVFB_DBGFLG_INFO (1 << 1) - -#define IVTVFB_DEBUG(x, type, fmt, args...) \ - do { \ - if ((x) & ivtvfb_debug) \ - printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \ - } while (0) -#define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args) -#define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args) - -/* Standard kernel messages */ -#define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->instance , ## args) -#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->instance , ## args) -#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args) - -/* --------------------------------------------------------------------- */ - -#define IVTV_OSD_MAX_WIDTH 720 -#define IVTV_OSD_MAX_HEIGHT 576 - -#define IVTV_OSD_BPP_8 0x00 -#define IVTV_OSD_BPP_16_444 0x03 -#define IVTV_OSD_BPP_16_555 0x02 -#define IVTV_OSD_BPP_16_565 0x01 -#define IVTV_OSD_BPP_32 0x04 - -struct osd_info { - /* Physical base address */ - unsigned long video_pbase; - /* Relative base address (relative to start of decoder memory) */ - u32 video_rbase; - /* Mapped base address */ - volatile char __iomem *video_vbase; - /* Buffer size */ - u32 video_buffer_size; - -#ifdef CONFIG_MTRR - /* video_base rounded down as required by hardware MTRRs */ - unsigned long fb_start_aligned_physaddr; - /* video_base rounded up as required by hardware MTRRs */ - unsigned long fb_end_aligned_physaddr; -#endif - - /* Store the buffer offset */ - int set_osd_coords_x; - int set_osd_coords_y; - - /* Current dimensions (NOT VISIBLE SIZE!) */ - int display_width; - int display_height; - int display_byte_stride; - - /* Current bits per pixel */ - int bits_per_pixel; - int bytes_per_pixel; - - /* Frame buffer stuff */ - struct fb_info ivtvfb_info; - struct fb_var_screeninfo ivtvfb_defined; - struct fb_fix_screeninfo ivtvfb_fix; - - /* Used for a warm start */ - struct fb_var_screeninfo fbvar_cur; - int blank_cur; - u32 palette_cur[256]; - u32 pan_cur; -}; - -struct ivtv_osd_coords { - unsigned long offset; - unsigned long max_offset; - int pixel_stride; - int lines; - int x; - int y; -}; - -/* --------------------------------------------------------------------- */ - -/* ivtv API calls for framebuffer related support */ - -static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase, - u32 *fblength) -{ - u32 data[CX2341X_MBOX_MAX_DATA]; - int rc; - - ivtv_firmware_check(itv, "ivtvfb_get_framebuffer"); - rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0); - *fbbase = data[0]; - *fblength = data[1]; - return rc; -} - -static int ivtvfb_get_osd_coords(struct ivtv *itv, - struct ivtv_osd_coords *osd) -{ - struct osd_info *oi = itv->osd_info; - u32 data[CX2341X_MBOX_MAX_DATA]; - - ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0); - - osd->offset = data[0] - oi->video_rbase; - osd->max_offset = oi->display_width * oi->display_height * 4; - osd->pixel_stride = data[1]; - osd->lines = data[2]; - osd->x = data[3]; - osd->y = data[4]; - return 0; -} - -static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd) -{ - struct osd_info *oi = itv->osd_info; - - oi->display_width = osd->pixel_stride; - oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel; - oi->set_osd_coords_x += osd->x; - oi->set_osd_coords_y = osd->y; - - return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5, - osd->offset + oi->video_rbase, - osd->pixel_stride, - osd->lines, osd->x, osd->y); -} - -static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window) -{ - int osd_height_limit = itv->is_out_50hz ? 576 : 480; - - /* Only fail if resolution too high, otherwise fudge the start coords. */ - if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH)) - return -EINVAL; - - /* Ensure we don't exceed display limits */ - if (ivtv_window->top + ivtv_window->height > osd_height_limit) { - IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n", - ivtv_window->top, ivtv_window->height); - ivtv_window->top = osd_height_limit - ivtv_window->height; - } - - if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) { - IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n", - ivtv_window->left, ivtv_window->width); - ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width; - } - - /* Set the OSD origin */ - write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04); - - /* How much to display */ - write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08); - - /* Pass this info back the yuv handler */ - itv->yuv_info.osd_vis_w = ivtv_window->width; - itv->yuv_info.osd_vis_h = ivtv_window->height; - itv->yuv_info.osd_x_offset = ivtv_window->left; - itv->yuv_info.osd_y_offset = ivtv_window->top; - - return 0; -} - -static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, - unsigned long ivtv_dest_addr, void __user *userbuf, - int size_in_bytes) -{ - DEFINE_WAIT(wait); - int got_sig = 0; - - mutex_lock(&itv->udma.lock); - /* Map User DMA */ - if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) { - mutex_unlock(&itv->udma.lock); - IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, " - "Error with get_user_pages: %d bytes, %d pages returned\n", - size_in_bytes, itv->udma.page_count); - - /* get_user_pages must have failed completely */ - return -EIO; - } - - IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n", - size_in_bytes, itv->udma.page_count); - - ivtv_udma_prepare(itv); - prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE); - /* if no UDMA is pending and no UDMA is in progress, then the DMA - is finished */ - while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) || - test_bit(IVTV_F_I_UDMA, &itv->i_flags)) { - /* don't interrupt if the DMA is in progress but break off - a still pending DMA. */ - got_sig = signal_pending(current); - if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags)) - break; - got_sig = 0; - schedule(); - } - finish_wait(&itv->dma_waitq, &wait); - - /* Unmap Last DMA Xfer */ - ivtv_udma_unmap(itv); - mutex_unlock(&itv->udma.lock); - if (got_sig) { - IVTV_DEBUG_INFO("User stopped OSD\n"); - return -EINTR; - } - - return 0; -} - -static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, - unsigned long dest_offset, int count) -{ - DEFINE_WAIT(wait); - struct osd_info *oi = itv->osd_info; - - /* Nothing to do */ - if (count == 0) { - IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n"); - return -EINVAL; - } - - /* Check Total FB Size */ - if ((dest_offset + count) > oi->video_buffer_size) { - IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n", - dest_offset + count, oi->video_buffer_size); - return -E2BIG; - } - - /* Not fatal, but will have undesirable results */ - if ((unsigned long)source & 3) - IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n", - (unsigned long)source); - - if (dest_offset & 3) - IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset); - - if (count & 3) - IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count); - - /* Check Source */ - if (!access_ok(VERIFY_READ, source + dest_offset, count)) { - IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n", - (unsigned long)source); - - IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n", - dest_offset, (unsigned long)source, - count); - return -EINVAL; - } - - /* OSD Address to send DMA to */ - dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase; - - /* Fill Buffers */ - return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count); -} - -static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned long p = *ppos; - void *dst; - int err = 0; - int dma_err; - unsigned long total_size; - struct ivtv *itv = (struct ivtv *) info->par; - unsigned long dma_offset = - IVTV_DECODER_OFFSET + itv->osd_info->video_rbase; - unsigned long dma_size; - u16 lead = 0, tail = 0; - - if (info->state != FBINFO_STATE_RUNNING) - return -EPERM; - - total_size = info->screen_size; - - if (total_size == 0) - total_size = info->fix.smem_len; - - if (p > total_size) - return -EFBIG; - - if (count > total_size) { - err = -EFBIG; - count = total_size; - } - - if (count + p > total_size) { - if (!err) - err = -ENOSPC; - count = total_size - p; - } - - dst = (void __force *) (info->screen_base + p); - - if (info->fbops->fb_sync) - info->fbops->fb_sync(info); - - /* If transfer size > threshold and both src/dst - addresses are aligned, use DMA */ - if (count >= 4096 && - ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { - /* Odd address = can't DMA. Align */ - if ((unsigned long)dst & 3) { - lead = 4 - ((unsigned long)dst & 3); - if (copy_from_user(dst, buf, lead)) - return -EFAULT; - buf += lead; - dst += lead; - } - /* DMA resolution is 32 bits */ - if ((count - lead) & 3) - tail = (count - lead) & 3; - /* DMA the data */ - dma_size = count - lead - tail; - dma_err = ivtvfb_prep_dec_dma_to_device(itv, - p + lead + dma_offset, (void __user *)buf, dma_size); - if (dma_err) - return dma_err; - dst += dma_size; - buf += dma_size; - /* Copy any leftover data */ - if (tail && copy_from_user(dst, buf, tail)) - return -EFAULT; - } else if (copy_from_user(dst, buf, count)) { - return -EFAULT; - } - - if (!err) - *ppos += count; - - return (err) ? err : count; -} - -static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) -{ - DEFINE_WAIT(wait); - struct ivtv *itv = (struct ivtv *)info->par; - int rc = 0; - - switch (cmd) { - case FBIOGET_VBLANK: { - struct fb_vblank vblank; - u32 trace; - - memset(&vblank, 0, sizeof(struct fb_vblank)); - - vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | - FB_VBLANK_HAVE_VSYNC; - trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; - if (itv->is_out_50hz && trace > 312) - trace -= 312; - else if (itv->is_out_60hz && trace > 262) - trace -= 262; - if (trace == 1) - vblank.flags |= FB_VBLANK_VSYNCING; - vblank.count = itv->last_vsync_field; - vblank.vcount = trace; - vblank.hcount = 0; - if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank))) - return -EFAULT; - return 0; - } - - case FBIO_WAITFORVSYNC: - prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); - if (!schedule_timeout(msecs_to_jiffies(50))) - rc = -ETIMEDOUT; - finish_wait(&itv->vsync_waitq, &wait); - return rc; - - case IVTVFB_IOC_DMA_FRAME: { - struct ivtvfb_dma_frame args; - - IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n"); - if (copy_from_user(&args, (void __user *)arg, sizeof(args))) - return -EFAULT; - - return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count); - } - - default: - IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd); - return -EINVAL; - } - return 0; -} - -/* Framebuffer device handling */ - -static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var) -{ - struct osd_info *oi = itv->osd_info; - struct ivtv_osd_coords ivtv_osd; - struct v4l2_rect ivtv_window; - int osd_mode = -1; - - IVTVFB_DEBUG_INFO("ivtvfb_set_var\n"); - - /* Select color space */ - if (var->nonstd) /* YUV */ - write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00); - else /* RGB */ - write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00); - - /* Set the color mode */ - switch (var->bits_per_pixel) { - case 8: - osd_mode = IVTV_OSD_BPP_8; - break; - case 32: - osd_mode = IVTV_OSD_BPP_32; - break; - case 16: - switch (var->green.length) { - case 4: - osd_mode = IVTV_OSD_BPP_16_444; - break; - case 5: - osd_mode = IVTV_OSD_BPP_16_555; - break; - case 6: - osd_mode = IVTV_OSD_BPP_16_565; - break; - default: - IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); - } - break; - default: - IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n"); - } - - /* Set video mode. Although rare, the display can become scrambled even - if we don't change mode. Always 'bounce' to osd_mode via mode 0 */ - if (osd_mode != -1) { - ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0); - ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode); - } - - oi->bits_per_pixel = var->bits_per_pixel; - oi->bytes_per_pixel = var->bits_per_pixel / 8; - - /* Set the flicker filter */ - switch (var->vmode & FB_VMODE_MASK) { - case FB_VMODE_NONINTERLACED: /* Filter on */ - ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1); - break; - case FB_VMODE_INTERLACED: /* Filter off */ - ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0); - break; - default: - IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n"); - } - - /* Read the current osd info */ - ivtvfb_get_osd_coords(itv, &ivtv_osd); - - /* Now set the OSD to the size we want */ - ivtv_osd.pixel_stride = var->xres_virtual; - ivtv_osd.lines = var->yres_virtual; - ivtv_osd.x = 0; - ivtv_osd.y = 0; - ivtvfb_set_osd_coords(itv, &ivtv_osd); - - /* Can't seem to find the right API combo for this. - Use another function which does what we need through direct register access. */ - ivtv_window.width = var->xres; - ivtv_window.height = var->yres; - - /* Minimum margin cannot be 0, as X won't allow such a mode */ - if (!var->upper_margin) - var->upper_margin++; - if (!var->left_margin) - var->left_margin++; - ivtv_window.top = var->upper_margin - 1; - ivtv_window.left = var->left_margin - 1; - - ivtvfb_set_display_window(itv, &ivtv_window); - - /* Pass screen size back to yuv handler */ - itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride; - itv->yuv_info.osd_full_h = ivtv_osd.lines; - - /* Force update of yuv registers */ - itv->yuv_info.yuv_forced_update = 1; - - /* Keep a copy of these settings */ - memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur)); - - IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", - var->xres, var->yres, - var->xres_virtual, var->yres_virtual, - var->bits_per_pixel); - - IVTVFB_DEBUG_INFO("Display position: %d, %d\n", - var->left_margin, var->upper_margin); - - IVTVFB_DEBUG_INFO("Display filter: %s\n", - (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); - IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); - - return 0; -} - -static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix) -{ - struct osd_info *oi = itv->osd_info; - - IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n"); - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id)); - fix->smem_start = oi->video_pbase; - fix->smem_len = oi->video_buffer_size; - fix->type = FB_TYPE_PACKED_PIXELS; - fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - fix->xpanstep = 1; - fix->ypanstep = 1; - fix->ywrapstep = 0; - fix->line_length = oi->display_byte_stride; - fix->accel = FB_ACCEL_NONE; - return 0; -} - -/* Check the requested display mode, returning -EINVAL if we can't - handle it. */ - -static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv) -{ - struct osd_info *oi = itv->osd_info; - int osd_height_limit; - u32 pixclock, hlimit, vlimit; - - IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); - - /* Set base references for mode calcs. */ - if (itv->is_out_50hz) { - pixclock = 84316; - hlimit = 776; - vlimit = 591; - osd_height_limit = 576; - } - else { - pixclock = 83926; - hlimit = 776; - vlimit = 495; - osd_height_limit = 480; - } - - if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) { - var->transp.offset = 24; - var->transp.length = 8; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - } - else if (var->bits_per_pixel == 16) { - /* To find out the true mode, check green length */ - switch (var->green.length) { - case 4: - var->red.offset = 8; - var->red.length = 4; - var->green.offset = 4; - var->green.length = 4; - var->blue.offset = 0; - var->blue.length = 4; - var->transp.offset = 12; - var->transp.length = 1; - break; - case 5: - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 15; - var->transp.length = 1; - break; - default: - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - break; - } - } - else { - IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel); - return -EINVAL; - } - - /* Check the resolution */ - if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) { - IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n", - var->xres, var->yres); - return -EINVAL; - } - - /* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */ - if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) || - var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size || - var->xres_virtual < var->xres || - var->yres_virtual < var->yres) { - IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n", - var->xres_virtual, var->yres_virtual); - return -EINVAL; - } - - /* Some extra checks if in 8 bit mode */ - if (var->bits_per_pixel == 8) { - /* Width must be a multiple of 4 */ - if (var->xres & 3) { - IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres); - return -EINVAL; - } - if (var->xres_virtual & 3) { - IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual); - return -EINVAL; - } - } - else if (var->bits_per_pixel == 16) { - /* Width must be a multiple of 2 */ - if (var->xres & 1) { - IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres); - return -EINVAL; - } - if (var->xres_virtual & 1) { - IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual); - return -EINVAL; - } - } - - /* Now check the offsets */ - if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) { - IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n", - var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual); - return -EINVAL; - } - - /* Check pixel format */ - if (var->nonstd > 1) { - IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd); - return -EINVAL; - } - - /* Check video mode */ - if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) && - ((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) { - IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK); - return -EINVAL; - } - - /* Check the left & upper margins - If the margins are too large, just center the screen - (enforcing margins causes too many problems) */ - - if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1) - var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2); - - if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481)) - var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) - - var->yres) / 2); - - /* Maintain overall 'size' for a constant refresh rate */ - var->right_margin = hlimit - var->left_margin - var->xres; - var->lower_margin = vlimit - var->upper_margin - var->yres; - - /* Fixed sync times */ - var->hsync_len = 24; - var->vsync_len = 2; - - /* Non-interlaced / interlaced mode is used to switch the OSD filter - on or off. Adjust the clock timings to maintain a constant - vertical refresh rate. */ - if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) - var->pixclock = pixclock / 2; - else - var->pixclock = pixclock; - - itv->osd_rect.width = var->xres; - itv->osd_rect.height = var->yres; - - IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n", - var->xres, var->yres, - var->xres_virtual, var->yres_virtual, - var->bits_per_pixel); - - IVTVFB_DEBUG_INFO("Display position: %d, %d\n", - var->left_margin, var->upper_margin); - - IVTVFB_DEBUG_INFO("Display filter: %s\n", - (var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off"); - IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB"); - return 0; -} - -static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct ivtv *itv = (struct ivtv *) info->par; - IVTVFB_DEBUG_INFO("ivtvfb_check_var\n"); - return _ivtvfb_check_var(var, itv); -} - -static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) -{ - u32 osd_pan_index; - struct ivtv *itv = (struct ivtv *) info->par; - - if (var->yoffset + info->var.yres > info->var.yres_virtual || - var->xoffset + info->var.xres > info->var.xres_virtual) - return -EINVAL; - - osd_pan_index = var->yoffset * info->fix.line_length - + var->xoffset * info->var.bits_per_pixel / 8; - write_reg(osd_pan_index, 0x02A0C); - - /* Pass this info back the yuv handler */ - itv->yuv_info.osd_x_pan = var->xoffset; - itv->yuv_info.osd_y_pan = var->yoffset; - /* Force update of yuv registers */ - itv->yuv_info.yuv_forced_update = 1; - /* Remember this value */ - itv->osd_info->pan_cur = osd_pan_index; - return 0; -} - -static int ivtvfb_set_par(struct fb_info *info) -{ - int rc = 0; - struct ivtv *itv = (struct ivtv *) info->par; - - IVTVFB_DEBUG_INFO("ivtvfb_set_par\n"); - - rc = ivtvfb_set_var(itv, &info->var); - ivtvfb_pan_display(&info->var, info); - ivtvfb_get_fix(itv, &info->fix); - ivtv_firmware_check(itv, "ivtvfb_set_par"); - return rc; -} - -static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - u32 color, *palette; - struct ivtv *itv = (struct ivtv *)info->par; - - if (regno >= info->cmap.len) - return -EINVAL; - - color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); - if (info->var.bits_per_pixel <= 8) { - write_reg(regno, 0x02a30); - write_reg(color, 0x02a34); - itv->osd_info->palette_cur[regno] = color; - return 0; - } - if (regno >= 16) - return -EINVAL; - - palette = info->pseudo_palette; - if (info->var.bits_per_pixel == 16) { - switch (info->var.green.length) { - case 4: - color = ((red & 0xf000) >> 4) | - ((green & 0xf000) >> 8) | - ((blue & 0xf000) >> 12); - break; - case 5: - color = ((red & 0xf800) >> 1) | - ((green & 0xf800) >> 6) | - ((blue & 0xf800) >> 11); - break; - case 6: - color = (red & 0xf800 ) | - ((green & 0xfc00) >> 5) | - ((blue & 0xf800) >> 11); - break; - } - } - palette[regno] = color; - return 0; -} - -/* We don't really support blanking. All this does is enable or - disable the OSD. */ -static int ivtvfb_blank(int blank_mode, struct fb_info *info) -{ - struct ivtv *itv = (struct ivtv *)info->par; - - IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode); - switch (blank_mode) { - case FB_BLANK_UNBLANK: - ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); - break; - case FB_BLANK_NORMAL: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_VSYNC_SUSPEND: - ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1); - break; - case FB_BLANK_POWERDOWN: - ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); - ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); - break; - } - itv->osd_info->blank_cur = blank_mode; - return 0; -} - -static struct fb_ops ivtvfb_ops = { - .owner = THIS_MODULE, - .fb_write = ivtvfb_write, - .fb_check_var = ivtvfb_check_var, - .fb_set_par = ivtvfb_set_par, - .fb_setcolreg = ivtvfb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_cursor = NULL, - .fb_ioctl = ivtvfb_ioctl, - .fb_pan_display = ivtvfb_pan_display, - .fb_blank = ivtvfb_blank, -}; - -/* Restore hardware after firmware restart */ -static void ivtvfb_restore(struct ivtv *itv) -{ - struct osd_info *oi = itv->osd_info; - int i; - - ivtvfb_set_var(itv, &oi->fbvar_cur); - ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info); - for (i = 0; i < 256; i++) { - write_reg(i, 0x02a30); - write_reg(oi->palette_cur[i], 0x02a34); - } - write_reg(oi->pan_cur, 0x02a0c); -} - -/* Initialization */ - - -/* Setup our initial video mode */ -static int ivtvfb_init_vidmode(struct ivtv *itv) -{ - struct osd_info *oi = itv->osd_info; - struct v4l2_rect start_window; - int max_height; - - /* Color mode */ - - if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32) - osd_depth = 8; - oi->bits_per_pixel = osd_depth; - oi->bytes_per_pixel = oi->bits_per_pixel / 8; - - /* Horizontal size & position */ - - if (osd_xres > 720) - osd_xres = 720; - - /* Must be a multiple of 4 for 8bpp & 2 for 16bpp */ - if (osd_depth == 8) - osd_xres &= ~3; - else if (osd_depth == 16) - osd_xres &= ~1; - - start_window.width = osd_xres ? osd_xres : 640; - - /* Check horizontal start (osd_left). */ - if (osd_left && osd_left + start_window.width > 721) { - IVTVFB_ERR("Invalid osd_left - assuming default\n"); - osd_left = 0; - } - - /* Hardware coords start at 0, user coords start at 1. */ - osd_left--; - - start_window.left = osd_left >= 0 ? - osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2); - - oi->display_byte_stride = - start_window.width * oi->bytes_per_pixel; - - /* Vertical size & position */ - - max_height = itv->is_out_50hz ? 576 : 480; - - if (osd_yres > max_height) - osd_yres = max_height; - - start_window.height = osd_yres ? - osd_yres : itv->is_out_50hz ? 480 : 400; - - /* Check vertical start (osd_upper). */ - if (osd_upper + start_window.height > max_height + 1) { - IVTVFB_ERR("Invalid osd_upper - assuming default\n"); - osd_upper = 0; - } - - /* Hardware coords start at 0, user coords start at 1. */ - osd_upper--; - - start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2); - - oi->display_width = start_window.width; - oi->display_height = start_window.height; - - /* Generate a valid fb_var_screeninfo */ - - oi->ivtvfb_defined.xres = oi->display_width; - oi->ivtvfb_defined.yres = oi->display_height; - oi->ivtvfb_defined.xres_virtual = oi->display_width; - oi->ivtvfb_defined.yres_virtual = oi->display_height; - oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel; - oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED); - oi->ivtvfb_defined.left_margin = start_window.left + 1; - oi->ivtvfb_defined.upper_margin = start_window.top + 1; - oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE; - oi->ivtvfb_defined.nonstd = 0; - - /* We've filled in the most data, let the usual mode check - routine fill in the rest. */ - _ivtvfb_check_var(&oi->ivtvfb_defined, itv); - - /* Generate valid fb_fix_screeninfo */ - - ivtvfb_get_fix(itv, &oi->ivtvfb_fix); - - /* Generate valid fb_info */ - - oi->ivtvfb_info.node = -1; - oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT; - oi->ivtvfb_info.fbops = &ivtvfb_ops; - oi->ivtvfb_info.par = itv; - oi->ivtvfb_info.var = oi->ivtvfb_defined; - oi->ivtvfb_info.fix = oi->ivtvfb_fix; - oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase; - oi->ivtvfb_info.fbops = &ivtvfb_ops; - - /* Supply some monitor specs. Bogus values will do for now */ - oi->ivtvfb_info.monspecs.hfmin = 8000; - oi->ivtvfb_info.monspecs.hfmax = 70000; - oi->ivtvfb_info.monspecs.vfmin = 10; - oi->ivtvfb_info.monspecs.vfmax = 100; - - /* Allocate color map */ - if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) { - IVTVFB_ERR("abort, unable to alloc cmap\n"); - return -ENOMEM; - } - - /* Allocate the pseudo palette */ - oi->ivtvfb_info.pseudo_palette = - kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN); - - if (!oi->ivtvfb_info.pseudo_palette) { - IVTVFB_ERR("abort, unable to alloc pseudo palette\n"); - return -ENOMEM; - } - - return 0; -} - -/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */ - -static int ivtvfb_init_io(struct ivtv *itv) -{ - struct osd_info *oi = itv->osd_info; - - mutex_lock(&itv->serialize_lock); - if (ivtv_init_on_first_open(itv)) { - mutex_unlock(&itv->serialize_lock); - IVTVFB_ERR("Failed to initialize ivtv\n"); - return -ENXIO; - } - mutex_unlock(&itv->serialize_lock); - - if (ivtvfb_get_framebuffer(itv, &oi->video_rbase, - &oi->video_buffer_size) < 0) { - IVTVFB_ERR("Firmware failed to respond\n"); - return -EIO; - } - - /* The osd buffer size depends on the number of video buffers allocated - on the PVR350 itself. For now we'll hardcode the smallest osd buffer - size to prevent any overlap. */ - oi->video_buffer_size = 1704960; - - oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase; - oi->video_vbase = itv->dec_mem + oi->video_rbase; - - if (!oi->video_vbase) { - IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n", - oi->video_buffer_size, oi->video_pbase); - return -EIO; - } - - IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", - oi->video_pbase, oi->video_vbase, - oi->video_buffer_size / 1024); - -#ifdef CONFIG_MTRR - { - /* Find the largest power of two that maps the whole buffer */ - int size_shift = 31; - - while (!(oi->video_buffer_size & (1 << size_shift))) { - size_shift--; - } - size_shift++; - oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1); - oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size; - oi->fb_end_aligned_physaddr += (1 << size_shift) - 1; - oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1); - if (mtrr_add(oi->fb_start_aligned_physaddr, - oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr, - MTRR_TYPE_WRCOMB, 1) < 0) { - IVTVFB_INFO("disabled mttr\n"); - oi->fb_start_aligned_physaddr = 0; - oi->fb_end_aligned_physaddr = 0; - } - } -#endif - - /* Blank the entire osd. */ - memset_io(oi->video_vbase, 0, oi->video_buffer_size); - - return 0; -} - -/* Release any memory we've grabbed & remove mtrr entry */ -static void ivtvfb_release_buffers (struct ivtv *itv) -{ - struct osd_info *oi = itv->osd_info; - - /* Release cmap */ - if (oi->ivtvfb_info.cmap.len) - fb_dealloc_cmap(&oi->ivtvfb_info.cmap); - - /* Release pseudo palette */ - if (oi->ivtvfb_info.pseudo_palette) - kfree(oi->ivtvfb_info.pseudo_palette); - -#ifdef CONFIG_MTRR - if (oi->fb_end_aligned_physaddr) { - mtrr_del(-1, oi->fb_start_aligned_physaddr, - oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr); - } -#endif - - kfree(oi); - itv->osd_info = NULL; -} - -/* Initialize the specified card */ - -static int ivtvfb_init_card(struct ivtv *itv) -{ - int rc; - - if (itv->osd_info) { - IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id); - return -EBUSY; - } - - itv->osd_info = kzalloc(sizeof(struct osd_info), - GFP_ATOMIC|__GFP_NOWARN); - if (itv->osd_info == NULL) { - IVTVFB_ERR("Failed to allocate memory for osd_info\n"); - return -ENOMEM; - } - - /* Find & setup the OSD buffer */ - rc = ivtvfb_init_io(itv); - if (rc) { - ivtvfb_release_buffers(itv); - return rc; - } - - /* Set the startup video mode information */ - if ((rc = ivtvfb_init_vidmode(itv))) { - ivtvfb_release_buffers(itv); - return rc; - } - - /* Register the framebuffer */ - if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) { - ivtvfb_release_buffers(itv); - return -EINVAL; - } - - itv->osd_video_pbase = itv->osd_info->video_pbase; - - /* Set the card to the requested mode */ - ivtvfb_set_par(&itv->osd_info->ivtvfb_info); - - /* Set color 0 to black */ - write_reg(0, 0x02a30); - write_reg(0, 0x02a34); - - /* Enable the osd */ - ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info); - - /* Enable restart */ - itv->ivtvfb_restore = ivtvfb_restore; - - /* Allocate DMA */ - ivtv_udma_alloc(itv); - return 0; - -} - -static int __init ivtvfb_callback_init(struct device *dev, void *p) -{ - struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - if (ivtvfb_init_card(itv) == 0) { - IVTVFB_INFO("Framebuffer registered on %s\n", - itv->v4l2_dev.name); - (*(int *)p)++; - } - } - return 0; -} - -static int ivtvfb_callback_cleanup(struct device *dev, void *p) -{ - struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); - struct ivtv *itv = container_of(v4l2_dev, struct ivtv, v4l2_dev); - struct osd_info *oi = itv->osd_info; - - if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { - if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { - IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", - itv->instance); - return 0; - } - IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); - itv->ivtvfb_restore = NULL; - ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info); - ivtvfb_release_buffers(itv); - itv->osd_video_pbase = 0; - } - return 0; -} - -static int __init ivtvfb_init(void) -{ - struct device_driver *drv; - int registered = 0; - int err; - - if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { - printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", - IVTV_MAX_CARDS - 1); - return -EINVAL; - } - - drv = driver_find("ivtv", &pci_bus_type); - err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); - (void)err; /* suppress compiler warning */ - if (!registered) { - printk(KERN_ERR "ivtvfb: no cards found\n"); - return -ENODEV; - } - return 0; -} - -static void ivtvfb_cleanup(void) -{ - struct device_driver *drv; - int err; - - printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n"); - - drv = driver_find("ivtv", &pci_bus_type); - err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); - (void)err; /* suppress compiler warning */ -} - -module_init(ivtvfb_init); -module_exit(ivtvfb_cleanup); |